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
.............
- movl $10, -8(%ebp) - So we put 10 into 2nd block from the bottom of the stack
.............
ebp
.............
.............
10
.............
.............
.............
.............
esp
.............
- movl $2, -4(%ebp) We put 2 in the 1st block from the bottom of the stack
.............
ebp
.............
2
.............
10
.............
.............
.............
.............
esp
.............
- movl -4(%ebp), %eax - We put 2 into the eax
.............
ebp
.............
2 <<--- eax
.............
10
.............
.............
.............
.............
esp
.............
- 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
.............
- movl -8(%ebp), %eax - We put 10 into eax
.............
ebp
.............
2
.............
10 <<--- eax
.............
.............
.............
2
.............
esp
.............
- movl %eax, (%esp) - We put 10 from eax in the esp .............
ebp
.............
2
.............
10 <<--- eax
.............
.............
.............
2
.............
10 <<---esp
.............
ret
.............
- 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 <<----
.............
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.
subl $16, %esp . esp has address of 4th block.
.............
2
.............
10
.............
ret
.............
ebp
.............
.............
.............
.............
esp <<----
.............
- movl 8(%ebp), %eax
So here we copy 10 to eax
imull 12(%ebp), %eax Then we take second argument 2 and multiply it with 10 which is in eax.
movl %eax, -4(%ebp) Then we move result from eax to the stack of mult function .............
2
.............
10
.............
ret
.............
ebp
.............
20 <<----
.............
.............
.............
esp
.............
-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.
mult
inmain
as part of this exercise -main
should really use a proper and meaningful return value. LikeEXIT_SUCCESS
in this case. – Iskar Jarak