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

As Zang MingJie has already said in a comment, test eax,eax is almost identical to cmp eax,0, except that it 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.


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.

Reference from: assembly_language_for_x86_processors.pdf

Tags:

Assembly

X86