In x86 what's difference between "test eax,eax" and "cmp eax,0"

30,594

Solution 1

As Zang MingJie has already said in a comment, test eax, eax is almost identical to cmp eax, 0, except that it is shorter than cmp, because with cmp you have to supply 0 as an argument. Note that the savings are not very large, because the 2nd operand gets sign-extended to match the size of the 1st operand, so it does not necessarily take a whole 4 bytes to represent that zero.

Now, what you are asking is whether there is any other difference. This is a reasonable question to ask, because cmp is an arithmetic operation, (it performs a subtraction and discards the result,) while test is a logical operation, (it performs a bitwise AND and discards the result,) so one could reasonably suspect that they may modify the Flags register differently.

As it turns out, both instructions modify the Flags register in an almost identical fashion. Both instructions modify the OF SF ZF AF PF and CF bits of the flags register. The test instruction always clears OF and CF, but that's also what cmp against zero does. The only other difference is that the cmp instruction will properly set the obscure AF flag, while the test instruction leaves the contents of that flag undefined. But in the case of cmp eax,0 the AF will always be cleared regardless of the value of eax, so there is nothing that you can learn from a cmp eax, 0 that you would not learn from a test eax, eax.

Therefore, I would conclude that there is no situation where test eax, eax will give you something that cmp eax, 0 will not, nor vice versa. The two instructions appear to be completely interchangeable for any practical or even not-so-practical purpose, except for saving a byte or two of instruction code.

Using test eax, eax instead of cmp eax, 0 shows that you know your assembly. It also shows that you prefer a slightly cryptic, and marginally better performing instruction over a straightforward, understandable instruction. This is the kind of thing that tends to earn bonus points from other geeks, but it has not had any practical usefulness in the real world in the last couple of decades or so.

Solution 2

#Difference(Theoretical)

As stated above in comment and accepted answer also that these instructions are almost identical when used this way, but then why there are two instructions in the instruction set if they are same?

Because they're different if used with different operands. The fact that test same,same works as a compare against zero is just a convenient consequence of how 2's complement and FLAGS work, making it a useful peephole optimization.

TEST instruction uses AND logic on the bit pairs from both the arg0 and arg1 and can check if a specific bit is set or not, then FLAGS set accordingly. (With the integer result discarded). Just like cmp sets FLAGS from a subtract while discarding the integer result.

#Operation(TEST)

HTML except from Intel's vol.2 PDF manual

TEMP ← SRC1 **AND** SRC2;
SF ← MSB(TEMP);
IF TEMP=0
    THEN ZF ← 1;
    ELSE ZF ← 0;
FI:

PF ← BitwiseXNOR(TEMP[0:7]);
CF ← 0;
OF ← 0;
(* AF is undefined *)

Flags Affected

The OF and CF flags are set to 0. The SF, ZF, and PF flags are set according to the result (see the “Operation” section above). The state of the AF flag is undefined.

(The TEST operation sets the flags CF and OF to zero. The SF is set to the most significant bit of the result of the AND. If the result is 0, the ZF is set to 1, otherwise set to 0.)


While CMP instruction uses SUB instruction and subtract arg1 from arg0 and will set CF(Carry Flag) and ZF(Zero Flag) based on given args to CMP instruction, if both are equal(arg1==arg0) then it's obvious that the result will be zero and ZF will be set to 1 and if arg0 > arg1 then no flag will be set(remains 0 for ZF and CF) and if arg0 < arg1 then ZF will remain 0 as they are not equal but CF will be set.

#Operation(CMP)

temp ← SRC1 − SignExtend(SRC2); 
ModifyStatusFlags; 
   (* Modify status flags in  the same manner as the SUB instruction*)

Flags Affected

The CF, OF, SF, ZF, AF, and PF flags are set according to the result.

Share:
30,594

Related videos on Youtube

Hind Forsum
Author by

Hind Forsum

Updated on October 09, 2022

Comments

  • Hind Forsum
    Hind Forsum over 1 year

    Is test eax, eax more efficient than cmp eax, 0? Is there any case that the test eax, eax is necessary where cmp eax, 0 doesn't fulfill requirement?

  • Peter Cordes
    Peter Cordes over 7 years
    There can be a perf difference on Intel Core2 or Nehalem, where TEST can macro-fuse with more flavours of JCC than CMP. e.g. Core2 and Nehalem can macro-fuse test eax,eax / js, but not cmp eax,0 / js. Nehalem can macro-fuse cmp eax,0 / jl, though. (Core2 can't, but Core2 can only macro-fuse at all in 32-bit mode). See Agner Fog's microarch pdf
  • Peter Cordes
    Peter Cordes about 5 years
    Specifically, see my answer on Test whether a register is zero with CMP reg,0 vs OR reg,reg? for more. (And re: "no practical usefulness in the real world": unless you're a compiler / JIT developer. Humans have to know how to create efficient asm before they can get machines to do it for them.)

Related