x86 Disassembly/Branch Examples

Example: Number of Parameters

edit

What parameters does this function take? What calling convention does it use? What kind of value does it return? Write the entire C prototype of this function. Assume all values are unsigned values.

 push ebp
 mov ebp, esp
 mov eax, 0
 mov ecx, [ebp + 8]
 cmp ecx, 0
 jne _Label_1
 inc eax
 jmp _Label_2
 :_Label_1
 dec eax
 : _Label_2
 mov ecx, [ebp + 12]
 cmp ecx, 0
 jne _Label_3
 inc eax
 : _Label_3
 mov esp, ebp
 pop ebp
 ret

This function accesses parameters on the stack at [ebp + 8] and [ebp + 12]. Both of these values are loaded into ecx, and we can therefore assume they are 4-byte values. This function doesn't clean its own stack, and the values aren't passed in registers, so we know the function is CDECL. The return value in eax is a 4-byte value, and we are told to assume that all the values are unsigned. Putting all this together, we can construct the function prototype:

 unsigned int CDECL MyFunction(unsigned int param1, unsigned int param2);

Example: Identify Branch Structures

edit

How many separate branch structures are in this function? What types are they? Can you give more descriptive names to _Label_1, _Label_2, and _Label_3, based on the structures of these branches?

 push ebp
 mov ebp, esp
 mov eax, 0
 mov ecx, [ebp + 8]
 cmp ecx, 0
 jne _Label_1
 inc eax
 jmp _Label_2
 :_Label_1
 dec eax
 : _Label_2
 mov ecx, [ebp + 12]
 cmp ecx, 0
 jne _Label_3
 inc eax
 : _Label_3
 mov esp, ebp
 pop ebp
 ret

How many separate branch structures are there in this function? Stripping away the entry and exit sequences, here is the code we have left:

 mov ecx, [ebp + 8]
 cmp ecx, 0
 jne _Label_1
 inc eax
 jmp _Label_2
 :_Label_1
 dec eax
 : _Label_2
 mov ecx, [ebp + 12]
 cmp ecx, 0
 jne _Label_3
 inc eax
 : _Label_3

Looking through, we see 2 cmp statements. The first cmp statement compares ecx to zero. If ecx is not zero, we go to _Label_1, decrement eax, and then fall through to _Label_2. If ecx is zero, we increment eax, and go to directly to _Label_2. Writing out some pseudocode, we have the following result for the first section:

if(ecx doesnt equal 0) goto _Label_1
eax++;
goto _Label_2
:_Label_1
eax--;
:_Label_2

Since _Label_2 occurs at the end of this structure, we can rename it to something more descriptive, like "End_of_Branch_1", or "Branch_1_End". The first comparison tests ecx against 0, and then jumps on not-equal. We can reverse the conditional, and say that _Label_1 is an else block:

 if(ecx == 0) ;ecx is param1 here
 {
    eax++;
 }
 else
 {
    eax--;
 }

So we can rename _Label_1 to something else descriptive, such as "Else_1". The rest of the code block, after Branch_1_End (_Label_2) is as follows:

 mov ecx, [ebp + 12]
 cmp ecx, 0
 jne _Label_3
 inc eax
 : _Label_3

We can see immediately that _Label_3 is the end of this branch structure, so we can immediately call it "Branch_2_End", or something else. Here, we are again comparing ecx to 0, and if it is not equal, we jump to the end of the block. If it is equal to zero, however, we increment eax, and then fall out the bottom of the branch. We can see that there is no else block in this branch structure, so we don't need to invert the condition. We can write an if statement directly:

 if(ecx == 0) ;ecx is param2 here
 {
    eax++;
 }

Example: Convert To C

edit

Write the equivalent C code for this function. Assume all parameters and return values are unsigned values.

 push ebp
 mov ebp, esp
 mov eax, 0
 mov ecx, [ebp + 8]
 cmp ecx, 0
 jne _Label_1
 inc eax
 jne _Label_2
 :_Label_1
 dec eax
 : _Label_2
 mov ecx, [ebp + 12]
 cmp ecx, 0
 jne _Label_3
 inc eax
 : _Label_3
 mov esp, ebp
 pop ebp
 ret

Starting with the C function prototype from answer 1, and the conditional blocks in answer 2, we can put together a pseudo-code function, without variable declarations, or a return value:

 unsigned int CDECL MyFunction(unsigned int param1, unsigned int param2)
 {
    if(param1 == 0)
    {
       eax++;
    }
    else
    {
       eax--;
    }
    if(param2 == 0)
    {
       eax++;
    }
 }

Now, we just need to create a variable to store the value from eax, which we will call "a", and we will declare as a register type:

 unsigned int CDECL MyFunction(unsigned int param1, unsigned int param2)
 {
    register unsigned int a = 0;
    if(param1 == 0)
    {
       a++;
    }
    else
    {
       a--;
    }
    if(param2 == 0)
    {
       a++;
    }
    return a;
 }

Granted, this function isn't a particularly useful function, but at least we know what it does.