1

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

AL = 0
TEST AL,AL
JNZ ...

enter image description here

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?

3

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.

7
  • 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
    – Jason
    Aug 9 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:
    – MarianD
    Aug 9 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.
    – MarianD
    Aug 9 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!
    – Jason
    Aug 9 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.
    – MarianD
    Aug 9 at 20:14
2

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.

1

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:

    enter image description here

    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.
7
  • 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?
    – Jason
    Aug 10 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?
    – Jason
    Aug 10 at 8:00
  • 1
    @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.
    – MarianD
    Aug 10 at 17:11
  • 1
    @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.
    – MarianD
    Aug 10 at 17:19
  • 1
    @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.)
    – MarianD
    Aug 10 at 20:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.