Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 562
Zeyad Etman Avatar asked Dec 15 '16 23:12

Zeyad Etman


People also ask

What is the fastest method to set a CPU register to zero?

Just use xor so you don't have to worry about which CPU recognizes which zeroing idiom. xor (being a recognized zeroing idiom, unlike mov reg, 0 ) has some obvious and some subtle advantages (summary list, then I'll expand on those):

How does TEST set the zero flag?

TEST sets the zero flag, ZF , when the result of the AND operation is zero. If two operands are equal, their bitwise AND is zero when both are zero. TEST also sets the sign flag, SF , when the most significant bit is set in the result, and the parity flag, PF , when the number of set bits is even.

Is there a zero register in x86?

The zero flag is a single bit flag that is a central feature on most conventional CPU architectures (including x86, ARM, PDP-11, 68000, 6502, and numerous others). It is often stored in a dedicated register, typically called status register or flag register, along with other flags.

What does TEST EAX EAX mean?

EAX is the register used by IA32 calling conventions to either return an interger value or a memory address to the calling routine. By design, strcpy can return either -1,0 or 1 in EAX with 0 indicating both strings match. TEST EAX,EAX tests whether EAX is zero or not and sets or unsets the ZF bit.


1 Answers

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.

like image 200
Ped7g Avatar answered Oct 09 '22 23:10

Ped7g