Search code examples
assemblyx86reverse-engineeringdisassembly

What does this assembly code do and what would the C code look like?


I'm trying to disassemble a file, and one of the sections contained this. What is this doing? What would it look like in C?

I believe it copies 40 to ebp-8 and copies 20 to ebp-4. Then it calls the func: function. That performs a few commands by adding edx to eax and then subtracts 4 from it. After it exits the func: function it adds 8 to esp. Am I on the right track?

func:
push ebp
mov ebp, esp
mov edx, DWORD PTR [ebp+8]
mov eax, DWORD PTR [ebp+12]
add eax, edx
sub eax, 4
pop ebp
ret
main:
push ebp
mov ebp, esp
sub esp, 16
mov DWORD PTR [ebp-8], 40
mov DWORD PTR [ebp-4], 20
push DWORD PTR [ebp-4]
push DWORD PTR [ebp-8]
call func
add esp, 8
leave
ret

EDIT: So would you agree that the result of the C would be the following?

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

int func(int d, int e)
{
    int sum = d + e;
    int result = sum - 4;
    return result;
}

int main(void)
{
    int a = 40;
    int b = 20;
    int c = func(a,b);
    printf("Result is: %d\n", c);
}

Solution

  • Broken down, the code looks like this:

    func:
    ; enter 0, 0
    push ebp
    mov ebp, esp
    ; entered func with no local variables
    
    ; get first param in edx
    mov edx, DWORD PTR [ebp+8]
    ; get second param in eax
    mov eax, DWORD PTR [ebp+12]
    
    add eax, edx    ; eax += edx
    sub eax, 4      ; eax -= 4
    
    ; to avoid segfault, you should first `mov esp, ebp` 
    ; but works here, since ESP was not changed, so getting back ESP's old value is not required
    pop ebp
    ret
    
    main:
    ; enter 16, 0
    push ebp
    mov ebp, esp
    sub esp, 16    ; adds 4 elements on the stack
    ; entered main with 4 local variables on stack
    
    ; writing on 2 local variables
    mov DWORD PTR [ebp-8], 40
    mov DWORD PTR [ebp-4], 20
    
    ; push 2 params on the stack and call `func`
    push DWORD PTR [ebp-4]    ; second param
    push DWORD PTR [ebp-8]    ; first param
    call func                 ; calls `func(first, second)`, returns EAX = 56
    
    ; delete 2 elements off the stack
    add esp, 8
    
    ; leave entered function (get back ESP from before entering)
    leave
    
    ; return to caller
    ret
    

    I think taken the explanation in the comments (marked by ;), it should be easy for you to translate it into a C code yourself.


    EDIT: As Peter Cordes marked out, Assembly does not know any data types such as int or long int. Im x86 assembling, you use the general registers and with the C Conventions, any 32bits value is returned in EAX, while 64bits values are returned in EDX:EAX, meaning the content of EDX will be the upper 32 bits.

    But if the main label is the classic int main() function in C and the entry point of the program, we can assume, that func looks like int func(int p1, int p2) as well in C, I believe, as the returned EDX is never used and the int main() function seems to end with return 56; with 56 in EAX.