# Help understanding x64 TEST instruction

I have read that TEST does a bitwise and on the two arguments. I have also read that jz and je are both equivalent, and jump if the zero flag is set. So here's the problem I'm struggling with. Consider the (rather useless) following code:

``````mov ax, 0x2
test ax, 0x2
je equal
mov ax, 0x0
jmp done
equal:
mov ax, 0x1
done:
``````

Logically, "jump if equal" should jump, but 0x2 & 0x2 should not set the zero flag. As I understand jz/je will jump if the zero flag is set, this means je is not logically doing what it implies ("jump if equal"). And in practice, the code will fall through and set ax to 0x0, rather than jumping and setting ax to 0x1.

Can anyone explain where my understanding is going wrong? Clearly I'm not understanding something correctly.

Thanks!

• Does this answer your question? What does the `TEST` instruction do Commented Sep 22, 2020 at 18:55
• @sudhackar Not really... it explains how I'd expect TEST to work, but then for JE it says "Jump short if equal (ZF=1)". However, this doesn't work that way at all, TEST doesn't set ZF=1 if the values are equal. I guess the question is, are TEST + JE simply not made to work together this way? CMP + JE work the way I'd expect. Commented Sep 22, 2020 at 23:13
• @blabb that should be an answer. Preferably embedding the shown code (which I find is a nice example) and the GIF. Commented Sep 23, 2020 at 9:00
• @0xC0000022L ok done thanks i would have written an answer earlier but i saw a close vote so i commented Commented Sep 23, 2020 at 9:17
• @blabb Don't be afraid of close votes. I don't remember the ins and outs, but to my knowledge there is a grace period if you start writing an answer and the question gets closed in the meantime. It's not protecting you indefinitely, but it allows you to answer a question that was since close. The close vote was probably cast by sudhackar, given the wording of the comment (it's the wording used most of the time for "duplicate" votes). Commented Sep 23, 2020 at 11:05

je is normally used with cmp instruction like

``````cmp Reg16/32/64,const
je someplace
``````

while jz is normally used to check specifically for 0 or null like

``````dec reg16/32/64
jz someplace
``````

i just modified your code to an infinite loop and emulated it in x86 emulator see below for code and gif.

code

``````mov ax, 0x2
dec     ax
and     ax, 0x1
jz  equal
je  equal
test    ax, 1
jz  equal
je  equal
cmp     ax, 1
redo:
jz  equal
equal:
je  redo
``````

• Thanks, that makes sense. The source of the inquiry was the assembly shown in Hopper Disassembler for a particular binary. It showed je instead of jz, but the code flow wasn't making sense. Now it does... seems like Hopper should have shown jz in this case. Commented Sep 23, 2020 at 17:57
• @T.Reed how would you expect Hopper to decide between JE/JZ aliases given that the instruction setting the flags the JE/Z is acting on might not be the one immediately before the JE/JZ ? The JE/JZ might even be the target of a jump ? Would the additional data/flow analysis needed to decide be worth it ? Perhaps it should also handle 3-way aliases too e.g. JC/JB/JNAE ? Commented Sep 27, 2020 at 15:17
• @IanCook It could show JZ instead of JE following a TEST instruction. But as you say, it may not be worth the trouble to implement that. Commented Sep 28, 2020 at 16:05