I am studying asm language by compiling c source code into asm langugae.
I ready known the call
instruction is equivalent of
push ret_address
jmp my_func
But it seem that calling a main function is quite different from calling a noraml function. For example:
// c source code. ret is a normal function.
long ret(long i)
{
return i++;
}
int main()
{
long i=0;
i = ret(i);
return i;
}
After compiled into asm, the asm code for main
and ret
function are:
Dump of assembler code for function main():
0x0000000100401096 <+0>: push %rbp
0x0000000100401097 <+1>: mov %rsp,%rbp
0x000000010040109a <+4>: sub $0x30,%rsp
0x000000010040109e <+8>: callq 0x100401160 <__main>
=> 0x00000001004010a3 <+13>: movq $0x0,-0x8(%rbp)
0x00000001004010ab <+21>: mov -0x8(%rbp),%rax
0x00000001004010af <+25>: mov %rax,%rcx
0x00000001004010b2 <+28>: callq 0x100401080 <ret(long)>
0x00000001004010b7 <+33>: mov %rax,-0x8(%rbp)
0x00000001004010bb <+37>: mov -0x8(%rbp),%rax
0x00000001004010bf <+41>: add $0x30,%rsp
0x00000001004010c3 <+45>: pop %rbp
0x00000001004010c4 <+46>: retq
Dump of assembler code for function ret(long):
0x0000000100401080 <+0>: push %rbp
0x0000000100401081 <+1>: mov %rsp,%rbp
0x0000000100401084 <+4>: mov %rcx,0x10(%rbp)
=> 0x0000000100401088 <+8>: mov 0x10(%rbp),%rax
0x000000010040108c <+12>: lea 0x1(%rax),%rdx
0x0000000100401090 <+16>: mov %rdx,0x10(%rbp)
0x0000000100401094 <+20>: pop %rbp
0x0000000100401095 <+21>: retq
When calling main()
, three instructions push %rbp
, mov %rsp,%rbp
,sub $0x30,%rsp
has already be executed.
Thus the call instruction will push the previous instruction stored in rip
register into the position (-$0x30 + %rsp), as sub $0x30,%rsp
has already exectuted. This is not how function calling stack works.
When calling ret()
, these three instructions are executed after call instruction, which is quite normal.
So is there something special for calling main()
? Why the asm code behaviors differently?