Stack contents during a function call

I'm trying to understand what will be present on the stack during a function call.

As far as I have learnt, arguments to the callee (if any), the return address of the caller and the base address would be pushed on the stack before calling another function.

So, I wrote a simple C program

#include <stdio.h>

void
foo()
{
}

int
main()
{
    foo();
    return 0;
}

and the corresponding dis-assembled machine code is

08048334 <foo>:
 8048334:   55                      push   %ebp
 8048335:   89 e5                   mov    %esp,%ebp
 8048337:   c9                      leave  
 8048338:   c3                      ret    

08048339 <main>:
 8048339:   55                      push   %ebp
 804833a:   89 e5                   mov    %esp,%ebp
 804833c:   83 ec 08                sub    $0x8,%esp
 804833f:   83 e4 f0                and    $0xfffffff0,%esp
 8048342:   b8 00 00 00 00          mov    $0x0,%eax
 8048347:   83 c0 0f                add    $0xf,%eax
 804834a:   83 c0 0f                add    $0xf,%eax
 804834d:   c1 e8 04                shr    $0x4,%eax
 8048350:   c1 e0 04                shl    $0x4,%eax
 8048353:   29 c4                   sub    %eax,%esp
 8048355:   e8 da ff ff ff          call   8048334 <foo>
 804835a:   b8 00 00 00 00          mov    $0x0,%eax
 804835f:   c9                      leave  
 8048360:   c3                      ret    
 8048361:   90                      nop    
 8048362:   90                      nop    
 8048363:   90                      nop    

While foo()'s code makes sense, I couldn't understand main's() code. Why is that there are so many operations? I was only expecting the following operations inside main()

    1. Push the frame pointer
    2. Call foo (which will inturn save the return address)

Can someone please explain me main()'s code? Thanks!


On x86 (which you might have tagged this as), the ABIs (application binary interface) demands the stack to be aligned to some boundary (16 bytes in this case) when a function is called. So when main() wants to call foo() , it first has to align the stack-pointer.


The first three lines of main

8048339:   55                      push   %ebp
804833a:   89 e5                   mov    %esp,%ebp
804833c:   83 ec 08                sub    $0x8,%esp

are called the function prologue. This set of instructions pushes the base pointer onto the stack, then assigns the base pointer the value of the current stack thus creating a new stack frame. The stack pointer is then decreased to reserve space for the function's local variables (which you don't have but is still done due to the calling convention). The next instruction

804833f:   83 e4 f0                and    $0xfffffff0,%esp

aligns the stack to the next lower 16 byte boundary. The following instructions

8048342:   b8 00 00 00 00          mov    $0x0,%eax
8048347:   83 c0 0f                add    $0xf,%eax
804834a:   83 c0 0f                add    $0xf,%eax
804834d:   c1 e8 04                shr    $0x4,%eax
8048350:   c1 e0 04                shl    $0x4,%eax
8048353:   29 c4                   sub    %eax,%esp

have appeared on SE a few times already (here, as pointed out by Paul R, and here,and again here). This routine seems to reserve additional space on the stack but does this in a strangely ineffective way. This section may depend on gcc version and OS and does not seem to be necessary.

The rest of the instructions calls foo and exits the program.

链接地址: http://www.djcxy.com/p/80374.html

上一篇: 调用函数后堆叠

下一篇: 在函数调用期间堆叠内容