8

This is my first program i am trying to reverse and my intro to this field.

The C program will test if two strings match, and it will printf() a message for each occasion.

This is what the reversed code snippet looks like:

call strcmp //compares the strings
test eax,eax
jne 1706

I know that jne will jump, if ZF=0.

What i do not understand is what's up with this line:

test eax,eax

What caused this line? How does it relate with strcmp?

I know that if the result of test is not zero, ZF=0, so jne will jump. But what does it compare exactly, and how does it relate to strcmp?

  • EAX is the register used by IA32 calling conventions to either return an interger value or a memory address to the calling routine. By design, strcpy can return either -1,0 or 1 in EAX with 0 indicating both strings match. TEST EAX,EAX tests whether EAX is zero or not and sets or unsets the ZF bit. – fpmurphy Sep 3 '18 at 15:41
  • strcpy returns an integer in EAX, not in FLAGS. See `testl` eax against eax? for how this instruction sets flags according to EAX. – Peter Cordes Sep 3 '18 at 20:13
13

Register eax will contain the return code from strcmp, after the call. The test eax, eax is the same as and eax, eax (bitwise and) except that it doesn't store the result in eax. So eax isn't affected by the test, but the zero-flag is, for example.

The test eax, eax is necessary to make the jne work in the first place. And jne is the same as jnz, just as je is the same as jz. Both act based on the ZF (zero-flag) value.

The jne branch will be taken if ZF=0 and therefore whenever strcmp returns a non-zero value (i.e. strings not equal). Conversely if eax contains zero upon return from strcmp, the jump via jne will not happen.

  • strcmp compares the strings and sets eax to zero if the strings are equal – josh Sep 3 '18 at 10:49
  • I mean, it does a logical AND. But what exactly does it checks? How will the jne, not fire? What would have to be the value of eax for jne to not jump? – user1584421 Sep 3 '18 at 10:55
  • What are the conditions for jne jumping and not jumping? What does eax have to be in order to jump/not jump? And how does this relates to strcmp? – user1584421 Sep 3 '18 at 11:20
  • 1
    @user1584421 think for a second and put together what you already know. eax contains the return value of strcmp. test is like bitwise and except it only sets the flags. Anding a value with itself gives the same value, so test eax, eax sets the flags based on whatever eax contains. ZF is set when the result of an operation is zero. jne jumps when ZF is not set. So the jump will be taken when strcmp returns nonzero, meaning the strings are unequal. – hobbs Sep 3 '18 at 16:42
9

You might be missing the fact that call strcmp will not set ZF for you - it returns the result in the EAX register. But JNE instruction tests ZF, and that test eax, eax serves to set ZF according to EAX. (actually, the opposite way, EAX=1 -> ZF=0).

I recommend reading some easy book on x86 assembly, it will help you a lot.

7

prototype of strcmp()

int strcmp(
   const char *string1,
   const char *string2 
);

the function returns an int whose interpretation is as follows
so i think that answers your question of when it jumps and when not
it jumps if eax is either > or < 0
it does not jump if eax == 0

Return Value
The return value for each of these functions indicates   
the lexicographic relation of string1 to string2.

< 0   string1 less than string2

  0   string1 identical to string2

> 0   string1 greater than string2

test eax,eax does a binary and of both inputs
and for it to jump eax needs to be 0 if eax is 0 test eax,eax will set the ZF to 1 else it will set the ZF to 0
normally test eax will be used if the program in higher languages test the result like this

if(!strcmp( a, b ) ) { do something } 

see a sample program and disassembly below

>>> eax = -1
>>> print eax & eax
-1
>>> eax = 0
>>> print eax & eax
0
>>> eax = 1
>>> print eax & eax
1
>>>

sample program

#include <stdio.h>
#include <string.h>

int main (void) {
    char *first="same";char *secon="same";char *third="diff";char *forth="tiff";
    int fis = strcmp(first,secon);
    int sec = strcmp(first,third);
    int tid = strcmp(first,forth);
    printf("%8x %8x %8x\n",fis,sec,tid);
    if(!strcmp(first,secon)){
        printf("trings are same \n");
    }
    if( strcmp(first,third) == 1 ) {
        printf("second string has a chareceter that is greater than first string\n");
    }
        if( strcmp(first,forth) == -1 ) {
        printf("second string has a chareceter that is lesser than first string\n");
    }

}

disassembly of main enter image description here

2

Basically, the original C code associated with this assembly code would be:

if (strcmp (str1, str2)) // call strcmp and do the 'test eax, eax'
  goto error; // str1 != str2 --> jne 1706

// str1 == str2
// Do legitimate code

error:
  // Do what you need to handle the error

If you want a way to remember what does test eax, eax it can be translated like this in C:

bool test = (eax == 0)

Note that eax is used to store the return code of a function, the test test eax, eax is very often used to check this return code after a call (usually, this is the converse and eax == 0 means that an error occurred).

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.