0
votes

So I create Assembly code from C and try to understand how it works. I need your help to clarify some points and tell me if I am analysing Assembly work in a right way.

Here is C code

int mult(int x, int y){
    int result = x * y;
    return result;
}

int main(int argc, char *argv[]){
    int x = 10;
    int y = 2;
    return mult(x, y);
}

And here is generated Assembly

mult:
.LFB0:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $16, %esp
    movl    8(%ebp), %eax
    imull   12(%ebp), %eax
    movl    %eax, -4(%ebp)
    movl    -4(%ebp), %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc

main:
.LFB1:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    subl    $24, %esp
    movl    $10, -8(%ebp)
    movl    $2, -4(%ebp)
    movl    -4(%ebp), %eax
    movl    %eax, 4(%esp)
    movl    -8(%ebp), %eax
    movl    %eax, (%esp)
    call    mult
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc

So how I understand the above Assembly: 1. pushl %ebp - We push ebp first and it will point to the bottom of our main stack 2. movl %esp, %ebp - Not exactly sure what is it, but I assume we just give same address for esp as is in ebp 3. subl $24, %esp - We give address for esp 6 blocks(which are of 4 bytes) down. Meaning that esp will have address of 6th block (here I am not sure if I placed esp in a right way). I showed my stack below

.............

ebp

.............

.............

.............

.............

.............

.............

esp

.............

  1. movl $10, -8(%ebp) - So we put 10 into 2nd block from the bottom of the stack

.............

ebp

.............

.............

10

.............

.............

.............

.............

esp

.............

  1. movl $2, -4(%ebp) We put 2 in the 1st block from the bottom of the stack

.............

ebp

.............

2

.............

10

.............

.............

.............

.............

esp

.............

  1. movl -4(%ebp), %eax - We put 2 into the eax

.............

ebp

.............

2 <<--- eax

.............

10

.............

.............

.............

.............

esp

.............

  1. movl %eax, 4(%esp) - We put 2 from eax to the 1st block from the top of the stack

.............

ebp

.............

2 <<--- eax

.............

10

.............

.............

.............

2

.............

esp

.............

  1. movl -8(%ebp), %eax - We put 10 into eax

.............

ebp

.............

2

.............

10 <<--- eax

.............

.............

.............

2

.............

esp

.............

  1. movl %eax, (%esp) - We put 10 from eax in the esp .............

ebp

.............

2

.............

10 <<--- eax

.............

.............

.............

2

.............

10 <<---esp

.............

ret

.............

  1. call mult - we call function mult.

So, what I understand we prepared 2 and 10 to serve as arguments by moving them to the very top of the stack. Then we pushed return address on the very top after the arguments. So the next block after the return address will be occupied by ebp of mult function. Correct?

Though, I do not understand why we had 2 blocks (meaning -12(%ebp) and -16(%ebp)) empty? I did not see any code in Assembly that bothered with those 2 block of 8 bytes. Why then stack of main was allocated for 24 bytes, but not 16 bytes? 1. pushl %ebp mult: .............

2

.............

10

.............

ret

.............

ebp <<----

.............

  1. Not sure what .cfi_def_cfa_offset 8 .cfi_offset 5, -8 means here... What it tells us? I also not sure what movl %esp, %ebp does. It copied esp address to ebp? I understand that it is basic stack initiation.

  2. subl $16, %esp . esp has address of 4th block.

.............

2

.............

10

.............

ret

.............

ebp

.............

.............

.............

.............

esp <<----

.............

  1. movl 8(%ebp), %eax

So here we copy 10 to eax

  1. imull 12(%ebp), %eax Then we take second argument 2 and multiply it with 10 which is in eax.

  2. movl %eax, -4(%ebp) Then we move result from eax to the stack of mult function .............

2

.............

10

.............

ret

.............

ebp

.............

20 <<----

.............

.............

.............

esp

.............

  1. -4(%ebp), %eax And then we again move it back to eax? Why would we do that? Not sure the purpose of these two instructions:

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

They cancel each other.. no?

Sorry for a long post. I will be thankful if you can clarify where my analysis was wrong and clarify some confusing points above.

1
At the very least, take some of this whitespace out.user1864610
Please reformat this question so that it is not needlessly long. Also, I hope you are only returning the result of mult in main as part of this exercise - main should really use a proper and meaningful return value. Like EXIT_SUCCESS in this case.Iskar Jarak
@MikeW if I take some whitespace out everything is just messes up. Stack Overflow puts everything in one line if you do not have a space between items.UserMoon
@FemX: That's not the only way. Please see: stackoverflow.com/help/formattingGreg Hewgill
@IskarJarak How would I reformat it? Unfortunately I did not find any table view in Stack Overflow edit window so I could not represent the stack in any other way... I specially showed stack after each instruction because I am not sure if I analyse everything in a right wayUserMoon

1 Answers

0
votes

You are getting ahead in steps 1 and 2 of your analysis.

pushl   %ebp           ;save ebp on the stack.
...
movl    %esp, %ebp     ;point ebp to the stack to access arguments and local variable space.
...
movl    %eax, -4(%ebp) ;move the product to result
movl    -4(%ebp), %eax ;return result

Not optimized, but that's what the function mult() does.