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?