212

Possible Duplicate:
x86 Assembly - ‘testl’ eax against eax?

I'm very very new to assembly language programming, and I'm currently trying to read the assembly language generated from a binary. I've run across

 test   %eax,%eax

or test %rdi, %rdi, etc. etc. I'm very confused as to what this does. Isn't the values in %eax, %eax the same? What is it testing? I read somewhere that it is doing the AND operation.....but since they are the same value, wouldn't it just return %eax?

The following is just one instance where I found this usage:

   400e6e:       85 c0                   test   %eax,%eax
   400e70:       74 05                   je     400e77 <phase_1+0x23>

I thought je jumps if the two values being compared are equal......well, because %eax is well, itself, in what situation would we NOT jump?

I'm a beginner to programming in general, so I'd appreciate it very much if someone could explain this to me. Thanks!

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
pauliwago
  • 6,373
  • 11
  • 42
  • 52
  • 6
    Since some answers seem a little bit unclear about it, let me point out that `TEST` updates other flags apart from `ZF` as well. See the instruction set reference. – Jester Oct 25 '12 at 12:15
  • @Jester fixed (in my answer), sorry. – John Dvorak Aug 19 '14 at 16:45
  • Another possible duplicate: [What does the `test` instruction do?](http://stackoverflow.com/q/6002079) – jww Oct 16 '15 at 00:56

5 Answers5

240

CMP subtracts the operands and sets the flags. Namely, it sets the zero flag if the difference is zero (operands are equal).

TEST sets the zero flag, ZF, when the result of the AND operation is zero. If two operands are equal, their bitwise AND is zero when both are zero. TEST also sets the sign flag, SF, when the most significant bit is set in the result, and the parity flag, PF, when the number of set bits is even.

JE [Jump if Equals] tests the zero flag and jumps if the flag is set. JE is an alias of JZ [Jump if Zero] so the disassembler cannot select one based on the opcode. JE is named such because the zero flag is set if the arguments to CMP are equal.

So,

TEST %eax, %eax
JE   400e77 <phase_1+0x23>

jumps if the %eax is zero.

John Dvorak
  • 26,799
  • 13
  • 69
  • 83
  • 8
    where can I find information like this? – Thorsten Staerk Aug 19 '14 at 15:14
  • 17
    namely? The list of x86 instructions [is on Wikipedia](http://en.wikipedia.org/wiki/X86_instruction_listings), which also links a [spec by Intel](http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html) as well as [another (quite readable) reference on wayback machine](http://web.archive.org/web/20100407092131/http://home.comcast.net/~fbui/intel.html). [A tutorial](http://en.wikibooks.org/wiki/X86_Assembly) is also available on Wikibooks. – John Dvorak Aug 19 '14 at 16:31
  • yes, this is the information I was looking for – Thorsten Staerk Aug 19 '14 at 16:39
  • 5
    Jumps if `%eax` is zero, that's what I was looking for. – dud3 Apr 03 '17 at 18:56
  • 1
    https://en.wikibooks.org/wiki/X86_Assembly/Control_Flow – Peter Chaula Apr 21 '17 at 09:04
  • `If two operands are equal, their bitwise AND is zero when both are zero.` therefore `AND`ing 2 numbers is useful only when both are 0, which will be the case in 1:100000 cases, that's pretty useless. or am I missing something? – metablaster Aug 29 '21 at 09:14
65

Some x86 instructions are designed to leave the content of the operands (registers) as they are and just set/unset specific internal CPU flags like the zero-flag (ZF). You can think at the ZF as a true/false boolean flag that resides inside the CPU.

in this particular case, TEST instruction performs a bitwise logical AND, discards the actual result and sets/unsets the ZF according to the result of the logical and: if the result is zero it sets ZF = 1, otherwise it sets ZF = 0.

Conditional jump instructions like JE are designed to look at the ZF for jumping/notjumping so using TEST and JE together is equivalent to perform a conditional jump based on the value of a specific register:

example:

TEST EAX,EAX
JE some_address



the CPU will jump to "some_address" if and only if ZF = 1, in other words if and only if AND(EAX,EAX) = 0 which in turn it can occur if and only if EAX == 0

the equivalent C code is:

if(eax == 0)
{
    goto some_address
}
Gianluca Ghettini
  • 11,129
  • 19
  • 93
  • 159
18

This checks if EAX is zero. The instruction test does bitwise AND between the arguments, and if EAX contains zero, the result sets the ZF, or ZeroFlag.

ppeterka
  • 20,583
  • 6
  • 63
  • 78
  • 3
    This is the standard way to do it. One could also do cmp %eax, 0 (immediate) for "clarity to beginners" but that would encode to a longer instruction (aka less efficient). – Aki Suihkonen Oct 25 '12 at 09:03
5

test is a non-destructive and, it doesn't return the result of the operation but it sets the flags register accordingly. To know what it really tests for you need to check the following instruction(s). Often out is used to check a register against 0, possibly coupled with a jz conditional jump.

Jens Björnhager
  • 5,632
  • 3
  • 27
  • 47
4

You are right, that test "and"s the two operands. But the result is discarded, the only thing that stays, and thats the important part, are the flags. They are set and thats the reason why the test instruction is used (and exist).

JE jumps not when equal (it has the meaning when the instruction before was a comparison), what it really does, it jumps when the ZF flag is set. And as it is one of the flags that is set by test, this instruction sequence (test x,x; je...) has the meaning that it is jumped when x is 0.

For questions like this (and for more details) I can just recommend a book about x86 instruction, e.g. even when it is really big, the Intel documentation is very good and precise.

flolo
  • 15,148
  • 4
  • 32
  • 57