'different between call instruction when calling main() and normal function for assembly language [duplicate]

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?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source