I have the following assembly code:

0000000000400711 <foo>:
  400711:   55                      push   rbp
  400712:   48 89 e5                mov    rbp,rsp
  400715:   48 89 7d e8             mov    QWORD PTR [rbp-0x18],rdi
  400719:   48 c7 45 f8 00 00 00    mov    QWORD PTR [rbp-0x8],0x0
  400720:   00
  400721:   eb 10                   jmp    400733 <foo+0x22>
  400723:   48 8b 45 e8             mov    rax,QWORD PTR [rbp-0x18]
  400727:   48 8d 50 ff             lea    rdx,[rax-0x1]
  40072b:   48 89 55 e8             mov    QWORD PTR [rbp-0x18],rdx
  40072f:   48 01 45 f8             add    QWORD PTR [rbp-0x8],rax
  400733:   48 83 7d e8 00          cmp    QWORD PTR [rbp-0x18],0x0
  400738:   75 e9                   jne    400723 <foo+0x12>
  40073a:   48 8b 45 f8             mov    rax,QWORD PTR [rbp-0x8]
  40073e:   5d                      pop    rbp
  40073f:   c3                      ret

I've been trying for several hours to figure out what this code does. From just trial and error with a C code to Assembly Code converter, I'm pretty sure the QWORD part comes from a char array, and the lines above it (push rbp, mov rbp, rsp) is just like a preamble. I'm really not sure how to interpret the lines that come after this. I tried storing the above code in as a file called "file.S" and then I used the following C code and terminal command to try and figure out what it does:

#include <stdio.h>
int foo(int, int);

int main()
{
   // printf() displays the string inside quotation
   printf("%d", foo(2,2));
   return 0;
}

The terminal command I used was

gcc -g -Og -no-pie -fno-pie -m32 main.c file.S

but I just get a whole bunch of errors.

I have tried for many hours, but I'm not making any progress with deciphering this code. Any help is much appreciated. In addition, is there a fast way (e.g. a decompiler) that can do this for me in the future? I couldn't find any of those either.

up vote 4 down vote accepted

First of all, this is 64bit assembly because of the registers (rax,..) and the memory address in the first line. So with the option -m32 that compiles to 32bit executables, you will get some problems.

You're right about the first part, push rbp and mov rbp,rsp is the function preamble.

mov    QWORD PTR [rbp-0x18],rdi
mov    QWORD PTR [rbp-0x8],0x0

These two QWORDS are not arguments but local variables. You can recognize this, because of the negative offset (variables are above the base pointer and the stack is growing towards lower addresses). x64 assembler gives the first arguments in registers, so the first line is a function argument. The second one is a local variable. Since they are QWORDS, the datatype has a length of 8 byte. The first instruction assigns the value of rdi to a local variable (say var_18) and the second assigns 0 to another local variable (say var_8).

jmp    400733 <foo+0x22>

This is an unconditional jump to the location 400733 meaning you will always jump there. So we need to continue at this location.

cmp    QWORD PTR [rbp-0x18],0x0
jne    400723 <foo+0x12>

At 400733 we see a compare instruction, followed by a conditional jump. The compare checks if the local variable var_18 is 0, if so the value of var_8 is returned (writing the value it to rax and return). Otherwise if not 0, we jump to 400723.

mov    rax,QWORD PTR [rbp-0x18]
lea    rdx,[rax-0x1]
mov    QWORD PTR [rbp-0x18],rdx
add    QWORD PTR [rbp-0x8],rax

Continuing at 400723 the first three instructions decrease the value of var_18 by 1. But the initial value before the subtraction is added to var_8. This seems a little confusing, but if you are familiar with C/C++, an instruction like var-- comes in mind, where you use the value of the variable before it is subtracted.

And then we are at the comparison to 0 again. So going over all these lines, it is obvious that this is a loop where the argument is a number which then acts as a counter, from which is counted down to zero. The second local variable var_8 is simply the sum of the different counter values. For example if var_18 has 5 then the result would be 5+4+3+2+1=15.

The corresponding C code would be similar to this.

long foo(long nr) {
    long var_8 = 0;

    while(nr != 0) {
        var_8 += nr--;
    } 
    return var_8;
}

In addition, is there a fast way (e.g. a decompiler) that can do this for me in the future? I couldn't find any of those either.

Yes, Hex-Rays Decompiler would do the job.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.