-3

I am writing assembly language in C. I was given the following assembly code:

fn:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $16, %esp
    movl    $1, -4(%ebp)
    jmp    .f2
.f3:
    movl    -4(%ebp), %eax
    imull   8(%ebp), %eax
    movl    %eax, -4(%ebp)
    subl    $1, 8(%ebp)
.f2:
    cmpl    $1, 8(%ebp)
     jg        .f3
    movl    -4(%ebp), %eax
    leave
    ret

I have written my code in C below:

     fn (int x)
     { 
         int y = 1;

         if(x  > 1):
              int z = y *=   x
              x – 1;

         return z;

}

Can someone tell me if I am on the right track with my C code? or if I am off and if I am can you point me in the right direction. Thank You in advanced

user2101463
  • 343
  • 1
  • 4
  • 14

1 Answers1

2
fn:
    pushl   %ebp
    movl    %esp, %ebp

This is the usual function startup used in the calling convertion __cdecl, save existing %ebp to the stack then save %esp (current stack address) to %ebp. %ebp will be from now on the reference to the stack call point of this function used by the assembly code to access both parameters and local variables. To conclude this function, the opposite will be done in the future, as well as setting the "return" value to %eax.

At this point you can assume %ebp points to the current stack position where the previous %ebp is stored, %ebp + 4 is the function's return point, and everything from %ebp + 8 on is the data of the function parameters. Negative values will be accessing unused stack space, where the function can store it's local variables.

    subl    $16, %esp

This is reserving 22 bytes of information in the stack for local variables. It can be 22 variables of 1 byte or 1 variable of 22 bytes, there is no way to know. It can reserve unused bytes to make stack alignment.

Its important to change the value of %esp at this point so any call to push, pop and call won't overwrite this function's local variables.

    movl    $1, -4(%ebp)

Here it is possible to assume that the first of the local variables present in this function is a 32-bits integer at the address %ebp - 4. It's value was just set to 1. Lets call this variable i.

    jmp    .f2
.f3:
    movl    -4(%ebp), %eax
    imull   8(%ebp), %eax

Based on what this imull is doing we can assume the function takes at least one parameter at the address %ebp + 8, and it seems its a 32-bits integer being multiplied by i. Lets call this parameter x.

    movl    %eax, -4(%ebp)

So far we can assume i = x * i.

    subl    $1, 8(%ebp)

And now x = x - 1.

.f2:
    cmpl    $1, 8(%ebp)
     jg        .f3

Here we are checking if x is greater than 1. If true, jumps to f3, that is a backward jump therefore it seems we have a loop going on.

    movl    -4(%ebp), %eax
    leave
    ret

Here outside the loop we see it set %eax to i and terminate the function, we can interpret it as return i.

Compiling the analyzed information together, we can assume the original function must have looked somewhat like this:

int fn(int x)
{
    int i = 1;
    while (x > 1)
    {
        i = i * x; // or just i *= x, same thing
        x = x - 1; // or just x--, same thing
    }
    return i;
}
Community
  • 1
  • 1
Havenard
  • 27,022
  • 5
  • 36
  • 62