Can someone tell me why these fail?

mov ebx,0
add ebx,-10
.if ebx<0
it's detected ebx as a negative number, so do something
.end if

or....

mov ebx,0
sub ebx,10
.if ebx<0
it's detected ebx as a negative number, so do something
.end if


It never detects ebx as being negative. It's baffling.
Posted on 2004-04-02 20:45:01 by sceptor
You have to use SDWORD PTR when you want to check signs in MASM :

mov ebx,0
add ebx,-10
.IF SDWORD PTR ebx < 0
etc...

or to check the flag sign :

mov ebx,0
add ebx,-10
.IF SIGN?

You can use real comparisons as well :

mov ebx,0
add ebx,-10
js @F
Posted on 2004-04-02 20:47:43 by donkey
Also, if you want to test a value for signedness at some arbitrary point in time, not after a calculation, you can test it's topmost bit - 80000000h in the case of a DWORD.
Posted on 2004-04-02 21:12:49 by f0dder
As well this is less of an issue if your not using registers. 32 bit registers are all by default defined purely as DWORDS. However, if your using local memory off the stack, you can define key variables directly without the need to reuse "SDWORD PTR" at every condition:
MyFunction PROC MyVariable[b]:SDWORD[/b]


...

.if MyVariable < 0
; Is negative
.else
; Is positive
.endif

ret
MyFunction ENDP


I figure its worth adding :alright:

Regards,
:NaN:
Posted on 2004-04-02 21:22:09 by NaN
OK, so it's a compiler thing. whew. I will test the flags themselves from now on.

Thanks guys.


Huh, I should have paid more attention to your post Nan. From what I gather from your post, if I declare a variable as SDWORD it will tell the compiler to test the flags? whether it's local or global?
Posted on 2004-04-02 21:45:32 by sceptor

Huh, I should have paid more attention to your post Nan. From what I gather from your post, if I declare a variable as SDWORD it will tell the compiler to test the flags? whether it's local or global?


Yup
Posted on 2004-04-02 21:56:54 by donkey
sceptor,


Huh, I should have paid more attention to your post Nan. From what I gather from your post, if I declare a variable as SDWORD it will tell the compiler to test the flags? whether it's local or global?


Nope! The assembler does not test the flags. The CPU does that when executing the conditional jump instructions. The assembler specifies what kind of conditional jump to execute. If you specify the default UNSIGNED comparison .IF EAX < 0, then the assembler will specify a JAE instruction. If you specify a SIGNED comparison .IF SDWORD PTR EAX < 0, then the assembler will specify a JGE instruction. Localness or globalization has nothing to do with this.

The most efficient way to test a register for positive, negative or zero that I know of is:


TEST EAX,EAX
.IF SIGN? ;is negative?
NOP
.ENDIF

TEST EAX,EAX
.IF !SIGN ;is positive or zero?
NOP
.ENDIF

TEST EAX,EAX
.IF ZERO? ;is zero?
NOP
.ENDIF


Ratch
Posted on 2004-04-03 00:17:31 by Ratch
Splitting hairs here Ratch,

The flags are tested. In reality the assembler does nothing at all but to encode the opcodes so it never actually tests anything at all or makes a single jump. If the instruction that the assembler encodes causes the flags to be tested then you can say that the assembler is causing the flags to be tested. JS cause the sign flag to be tested, so by using I can say that I am testing the sign flag and jumping if set.

It's not like the .IF etc.. gives you anything close to opcode level control over your application so the exact sequence is not know until after compile. For example MASM will encode the following :

.IF eax == 0
NOP
.ENDIF

as :

0040100B >/$ 0BC0 OR EAX,EAX
0040100D |. 75 01 JNZ SHORT DlgTest.00401010
0040100F |. 90 NOP
Posted on 2004-04-03 01:22:44 by donkey
donkey,
I just wanted to make sure that the OP understood that testing for conditional jumps takes place during execution, not during assembly. His previous post said otherwise.

Too bad MASM uses OR instead of TEST for specifying the setting of ZF, PF, SF, etc for a single register. The TEST instruction is marginally better. That is why I automatically use the code in my last post for conditional branching. Ratch
Posted on 2004-04-03 07:05:23 by Ratch
Hi Ratch,

My tests show them as equivalent :

rdtsc

mov esi,eax
mov ecx,100000
:
cld
test eax,eax
dec ecx
jnz <
rdtsc
sub eax,esi
PrintDec(eax)

rdtsc
mov esi,eax
mov ecx,100000
:
cld
or eax,eax
dec ecx
jnz <
rdtsc
sub eax,esi
PrintDec(eax)

rdtsc
mov esi,eax
mov ecx,100000
:
cld
test eax,eax
dec ecx
jnz <
rdtsc
sub eax,esi
PrintDec(eax)

rdtsc
mov esi,eax
mov ecx,100000
:
cld
or eax,eax
dec ecx
jnz <
rdtsc
sub eax,esi
PrintDec(eax)

Line 50: eax = 1200036 TEST
Line 62: eax = 1200036 OR
Line 74: eax = 1200038 TEST
Line 86: eax = 1200036 OR
Posted on 2004-04-03 08:15:32 by donkey
donkey,
Interesting. Maybe the CPU is smart enough to know that it does not have to write back to the register for an OR instruction if the register is the same, or it has enough time to do it in either case without slowing down. Now the question is whether it is true in all code situations and on different phylums and species of CPU's. Ratch
Posted on 2004-04-03 09:44:07 by Ratch
Hi Ratch,

I ran the test in other coding situations and it was TEST that perfomed worse, there were times that for some reason it would not pair and 100,000 itterations resulted in 100,000 extra clocks for TEST, OR was stable in all situations.
Posted on 2004-04-03 10:06:49 by donkey
donkey,
Who would have though that would be the case? Will wonders ever cease? Ratch
Posted on 2004-04-03 11:54:21 by Ratch
Hi Ratch,

Maybe OR goes directly to the RISC core and TEST does not, after all it is a fundamental boolean operator. Who knows, but I have always used OR and I have found that most assembler authors end up using it as well, GoAsm and MASM both prefer OR to TEST, that is enough of an endorsement for me.

The optimization manual only says TEST is preferred over AND and CMP, it doesn't mention OR.
Posted on 2004-04-03 12:37:58 by donkey
This is totaly baseless, but i was told along time ago to use OR instead of TEST. At this time, i cant even remember why, but its now the only way i do it.

I guess its like Ratch and his preference to TEST. Once you get in this habbit you dont look back or question it yourself.

:NaN:
Posted on 2004-04-03 15:57:20 by NaN
Nan Wrote:
This is totaly baseless, but i was told along time ago to use OR instead of TEST. At this time, i cant even remember why, but its now the only way i do it.

I guess its like Ratch and his preference to TEST. Once you get in this habbit you dont look back or question it yourself.

:NaN:

It could also be one of the special handling opcodes like xcgh eax,eax which is a one byte NOP that is even faster than a regular NOP. Actually Intel says to use it instead of a NOP.
Posted on 2004-04-03 16:03:09 by donkey
ahem. xchg eax, eax == nop... both are 90h.
Posted on 2004-04-03 17:27:53 by f0dder
TEST is obviously better. Only immature programmers uses OR. Ratch.
Posted on 2004-04-03 18:49:35 by comrade
comrade,
Donkey ran a timing on TEST and OR, and found OR to be faster. I thought TEST would be faster because no write back to a register is necessary. Could you take this discussion further and tell us how TEST is "obviously" better? Ratch
Posted on 2004-04-03 19:04:20 by Ratch
Hi Ratch,

After playing for most of the day, I may have jumped the gun, It was an alignment that made TEST appear slower in some cases. It was never faster than OR, but it may actually be equivalent in all cases that the function is equivalent. For example if you remove the CLD to allow pairing with the previous instruction this was the result:

Line 50: eax = 200050 TEST
Line 62: eax = 200050 OR
Line 74: eax = 300047 TEST
Line 86: eax = 200050 OR

Align 16 version

Line 50: eax = 200058 TEST
Line 62: eax = 200050 OR
Line 74: eax = 200050 TEST
Line 86: eax = 200050 OR

It was not a pairing problem as I originally surmised as the code is now identical in both TEST loops.

Also it does not appear to be a "smart processor" thing as TEST EAX,EBX/OR EAX,EBX reports this

Line 50: eax = 200050 TEST
Line 64: eax = 200047 OR
Line 74: eax = 200050 TEST
Line 86: eax = 200051 OR

I agree with you, if Comrade has specific tests to show that TEST is even marginally better than OR, I would like to see them. Just to say that this is for inexperienced programmers without proof is nonsense, the assembly programmers at Microsoft and Jeremy Gordon (author of GoAsm) are hardly "Newbies".
Posted on 2004-04-03 19:33:58 by donkey