# TEST instruction and ZF flag

In the part 07 of lena151 RE tutorial, we arrive to these instructions:

``````AL = 0
TEST AL,AL
JNZ ...
`````` And notice:

Because of the JNZ, AL must be different from zero when arriving here to be registered.

My question is: Why the AL must be different from zero? If 2 value (0=0) are equal, the Z flag set to 1, because the result of comparison is true! Is this right?

Why the zero flag must be different from zero?

It is a little confusing, but the Zero Flag is set (i.e. its value is 1), if the last result IS zero:

• result is `0` ⇒ ZF is not `0`
• result is not `0` ⇒ ZF is `0`

In general, a flag is set to show that the appropriate condition is true, or the appropriate event arised. (We also say that the flag is on (`1`) or off (`0`)).

BTW., this may be also a little counter-intuitive: `JNZ` (Jump if Not Zero) jumps if `ZF` is zero (because it means “not zero in the last result”, not “not zero in the Zero Flag”).

It's better to think only in terms of results, ignoring Zero Flag - flags are mainly technical tools for machines, not for us humans.

if 2 value (0=0) equal , the Z flag set to 1, because the result of compare is true! Is this right?

Not quite:

• In the case of the `CMP` comparison, zero means “their difference is zero”, so they are the same, but

• in the case of the `TEST AL,AL`, zero means `AND AL,AL` is zero”, i.e. `AL` itself is zero:

The instruction `TEST AL,AL` results in zero if and only if the value of AL itself is zero, too.

The explanation, why:

• if the value of `AL` is zero (all its bits are 0):

``````     0 0 0 0 0 0 0 0   ← AL
AND  0 0 0 0 0 0 0 0   ← AL
--------------------
0 0 0 0 0 0 0 0   ← zero     (ZF is set to 1)
``````
• the value of `AL` is not zero (i.e. at least one of its bits is 1):

``````     0 0 1 0 0 0 0 0   ← AL
AND  0 0 1 0 0 0 0 0   ← AL
--------------------
0 0 1 0 0 0 0 0     ← nonzero  (ZF is reset to 0)
``````

Why (bit-wise) `AND`, and not `TEST`?

Because the `TEST` instruction does the same as the `AND` does — the only difference is that the result of the bit-wise `AND` operation is for the `TEST` instruction discarded, so only the Zero Flag (ZF) is set or reset.

• Thank you very much. i edit my question. you help me alot. lena says the al must be different from 0. why? 0=0 is true and set the z flag! and jump . right? but in this case if AL is set to 1 again 1=1 and set the z flag and agin will jump. The Z flag will never be clean by any number. that's why i confused Aug 9, 2021 at 19:49
• @Jason, please don't change directly your question if it has already an answer, because it may the existing answer invalidate. It is better to append an EDIT: to it. So now I will answer your comment in the following one: Aug 9, 2021 at 19:56
• @Jason, if `AL` is zero, then `TEST AL,AL` is zero, too, and the next instruction `JNZ ...` will do nothing - and you want to jump over the bad boy, don't you? So the zero value in the `AL` is not what you want. Aug 9, 2021 at 20:01
• Yes , i want to jump over the badboy. i know how do it. but i'm confusing in TEST AL,AL section. The value of AL=0 , TEST AL,AL will set the zero flag. and if AL=1 TEST AL,AL will clear the zero flag. and i confusing for this one! Aug 9, 2021 at 20:08
• @Jason, as I explained in my answer, it may be a little to counter-intuitive. My recipe is not to concentrate on the `ZF` (it's only a flag), but only to the result. (OK, the `TEST` instruction only set or reset the Zero Flag, but we have no difficulty to pretend that it give the (discarded) result. Aug 9, 2021 at 20:14

You seem to have the idea that ZF generally means that the operands were equal. This is wrong. It is not a property of the ZF that it shows whether the operands were equal. Instead, it is a property of `CMP` that it sets the zero flag if the operands are equal. This code snippet does not execute `CMP`.

Instead, this code snippet executes `TEST`, which works differently. It says ZF exactly in those cases where no bit is set in both the first and the second operand. So if AL is nonzero, `TEST AL,AL` will find that some bits (all that are set in AL) are set in both the first and the second operand, and clear ZF. On the other hand, if AL is zero, no bit in AL is set, so there is no bit that is set in either the first or second operand, and ZF will be set.

The test for zero can be performed with the same effect using either `TEST`, `AND` or `OR`, where both operands are the same register. You will find all three variants in real-world code to test whether a register is zero.

Let's go into the important instructions in the reversed order.

1. `JNZ ...`

Jump if Not Zero. You want to jump (over the "bad boy"), i.e. you want to obtain "Not Zero" in this (previous) instruction:

2. `TEST AL,AL`

To obtain "Not Zero", the value in AL have to be "Not Zero", too.
The value of AL is set in this (previous) instruction:

3. `CALL ...`

This instruction calls a function, and this function fills the EAX register with its return value (in concordance with the calling convention). The AL register is a part of EAX: So you want from this function to return some "Not Zero", but it stubbornly returns 0 (meaning "Not Registered").

You have some natural possibilities to reach your desired behavior (jumping over the "bad boy"), but at first I remind the original order of instructions:

``````CALL ...
TEST AL,AL
JNZ ...
``````
1. Replace the `JNZ ...` instruction with `JMP ...` or `JZ ...`.
2. Replace the `TEST AL,AL` instruction with a such one which gives you a "Not Zero" result.
3. Replace the `CALL ...` instruction with a such one which fills the AL register with a "Not Zero".
4. Deep into the function in the `CALL ...` instruction and change it to return a "Not Zero" value.
• Thank you very much. i'm lost in assembly code. JNZ mean : Jump if Not Zero Set (zf = 0) right? And it must have 0 value? am i right? Aug 10, 2021 at 7:38
• JNZ is same JNE ? i saw that in CMP instruction like : (EAX = -1 )CMP EAX,-1 , JNE Short ... . So in this case we must see that the comparison is equal or not. right? or we should see result of EAX? Aug 10, 2021 at 8:00
• @Jason - "JNZ mean : Jump if Not Zero Set (zf = 0) right?" - No. Forget about flags, they will confuse you. JNZ means: Jump if the last result was Not Zero. Aug 10, 2021 at 17:11
• @Jason - "JNZ is same JNE ?" - Yes, it is. One and the same machine instruction may have more than 1 mnemonics to help us, humans. - "CMP EAX,-1 , JNE Short ... . So in this case we must see that the comparison is equal or not. right? " - Yes, you're right. - "or we should see result of EAX?" - No. The CMP instruction internally makes the difference between the first and the second operand, set a flag (or more flags), and then discards the result. No operand is changed, so you will not see the result in EAX, because it keeps its original value. Aug 10, 2021 at 17:19
• @Jason - "I saw oldest post that someone said the JNZ mean, Jump if Not Zero Flag Set !" - it is not correct, of course... - All your other questions you answered yourself correctly. - May I recommend you A Crash Course in x86 Assembly for Reverse Engineers? (PDF, only 26 pages.) Aug 10, 2021 at 20:37