Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
721 views
in Technique[技术] by (71.8m points)

assembly - What's the easiest way to determine if a register's value is equal to zero or not?

I'm using x86 assembly with the Irvine library.

What's the easiest way to check if a register value is equal to zero or not?

I used cmp instruction but i'm searching for alternative way. This is my code using cmp instruction and the register is ebx

    cmp ebx,0
    je equ1
    mov ebx,0
    jmp cont
equ1:
    mov ebx,1
    jmp cont
cont:
    exit

This "booleanizes" a value, producing a 0 or 1 like int ebx = !!ebx would in C.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Probably the "easiest", or simplest, "not-caring about details" answer how to determine is:

    ; here ebx is some value, flags are set to anything
    test   ebx,ebx   ; CF=0, ZF=0/1 according to ebx
    jz     whereToJumpWhenZero
    ; "non-zero ebx" will go here

    ; Or you can use the inverted "jnz" jump to take
    ; a branch when value was not zero instead of "jz".

There's a detailed answer from Peter Cordes to "testl eax against eax?" question reasoning about flags being set, etc. Also has a link to yet another similar answer, but reasoning about why it is best way from performance point of view. :)

How to set some other register (I will pick eax) to 1 when ebx is zero, and to 0 when ebx is non-zero (non destructive way for ebx itself):

    xor   eax,eax  ; eax = 0 (upper 24 bits needed to complete "al" later)
    test  ebx,ebx  ; test ebx, if it is zero (ZF=0/1)
    setz  al       ; al = 1/0 when ZF=1/0 (eax = 1/0 too)

Or how to convert ebx itself into 1/0 when ebx is zero/non-zero:

    neg   ebx      ; ZF=1/0 for zero/non-zero, CF=not(ZF)
    sbb   ebx,ebx  ; ebx = 0/-1 for CF=0/1
    inc   ebx      ; 1 when ebx was 0 at start, 0 otherwise

Or how to convert ebx itself into 1/0 when ebx is zero/non-zero, other variant (faster on "P6" to "Haswell" cores):

    test  ebx,ebx  ; ZF=1/0 for zero/non-zero ebx
    setz  bl       ; bl = 1/0 by ZF (SETcc can target only 8b r/m)
    movzx ebx,bl   ; ebx = bl extended to 32 bits by zeroes

etc, etc... It depends what happens before your testing, and also what you really want as output of test, there're many possible ways (optimal for different situations, and optimal for different target CPU).


I will add few more extremely common situations... A counter-loop down-counting from N to zero, to loop N times:

    mov   ebx,5   ; loop 5 times
exampleLoop:
    ; ... doing something, preserving ebx
    dec   ebx
    jnz   exampleLoop ; loop 5 times till ebx is zero

How to process 5 elements of word (16b) array (accessing them in array[0], array[1], ... order):

    mov   ebx,-5
    lea   esi,[array+5*2]
exampleLoop:
    mov   ax,[esi+ebx*2]  ; load value from array[i]
    ; process it ... and preserve esi and ebx
    inc   ebx
    jnz   exampleLoop  ; loop 5 times till ebx is zero

One more example, I somehow like this one a lot:

How to set target register (eax in example) to ~0 (-1)/0 when ebx is zero/non-zero and you already have value 1 in some register (ecx in example):

    ; ecx = 1, ebx = some value
    cmp   ebx,ecx  ; cmp ebx,1 => CF=1/0 for ebx zero/non-zero
    sbb   eax,eax  ; eax = -1 (~0) / 0 for CF=1/0 ; ebx/ecx intact

The -1 may look as practical as 1 (for indexing purposes at least), but -1 works also as full bitmask for further and/xor/or operations, so sometimes it is more handy.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...