tags:

views:

4980

answers:

6

Hi All,

I am trying to understand some assembly.

Assembly as follows, I am interested in the testl line:

000319df  8b4508         movl    0x08(%ebp),%eax  
000319e2  8b4004         movl    0x04(%eax),%eax  
000319e5  85c0       testl           %eax,%eax  
000319e7  7407       je    0x000319f0

I am trying to understand that point of 'testl' between %eax and %eax? I think the specifics of what this code isn't important, I am just trying to understand the test with itself - wouldn't the value always be true?

Thanks!

+11  A: 

It tests whether eax is 0, or above, or below. In this case, the jump is taken if eax is 0.

P.S. Oh, and hi! Small world. :-)

Chris Jester-Young
+9  A: 

The meaning of 'test' is to AND the arguments together, and check the result for zero. So this code tests if EAX is zero or not. 'je' will jump if zero.

BTW, this generates a smaller instruction that 'cmp eax,0' which is the reason that compilers will generally do it this way.

+1  A: 

If eax is zero it will perform the conditional jump, otherwise it will continue execution at 319e9

Mike Thompson
+6  A: 

The test instruction does a logical AND-operation between the operands but does not write the result back into a register. Only the flags are updated.

In your example the test eax, eax will set the zero flag if eax is zero, the sign-flag if the highest bit set and some other flags as well.

The Jump if Equal (je) instruction jumps if the zero flag is set.

You can translate the code to a more readable code like this:

cmp eax, 0
je  somewhere

That has the same functionality but requires some bytes more code-space. That's the reason why the compiler emitted a test instead of a compare.

Nils Pipenbrinck
Actually, cmp might not work there. That is, it works for the specific case presented, but cmp affects flags differently than test does, due to it being an internal sub instead of and. Something to keep in mind.
Cody Brocious
for a test against zero it's perfectly valid.
Nils Pipenbrinck
But you don't know what else looks at the flags later. The effects on flags are very different, so this can be an issue and very frequently is.
Cody Brocious
still, has some interesting and possibly useful information
maxpenguin
@Cody: As far as I can tell, the only flags that differ between the two are carry and overflow; doesn't seem like much of an obstacle to using 'test eax,eax' IMHO
No, the only flags that are set by a different /method/ are carry and overflow, both of which are set to 0. The /values/ of the other flags will differ because cmp uses sub and test uses and.
Cody Brocious
+1  A: 

This snippet of code is from a subroutine that was given a pointer to something, probably some struct or object. The 2nd line dereferences that pointer, fetching a value from that thing - possibly itself a pointer or maybe just an int, stored as its 2nd member (offset +4). The 3rd and 4th lines test this value for zero (NULL if it's a pointer) and skip the following few operations (not shown) if it is zero.

The test for zero sometimes is coded as a compare to an immediate literal zero value, but the compiler (or human?) who wrote this might have thought a testl op would run faster - taking into consideration all the modern CPU stuff like pipelining and register renaming. It's from the same bag of tricks that holds the idea of clearing a register with XOR EAX,EAX (which i saw on someone's license plate in Colorado!) rather than the obvious but maybe slower MOV EAX, #0 (i use an older notation).

In asm, like perl, TMTOWTDI.

DarenW
A: 

Thank you for this