在函数调用期间堆叠内容

我试图理解函数调用期间堆栈中将出现什么。

据我所知,在调用另一个函数之前,被调用者的参数(如果有的话),调用者的返回地址和基地址将被压入堆栈。

所以,我写了一个简单的C程序

#include <stdio.h>

void
foo()
{
}

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

并且相应的分解机器码是

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    

虽然foo()的代码有意义,但我无法理解main的()代码。 为什么有这么多的操作? 我只在main()中期待以下操作

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

有人可以解释我的main()的代码吗? 谢谢!


在x86上(您可能已将其标记为),ABI(应用程序二进制接口)要求在调用函数时将堆栈对齐到某个边界(本例中为16个字节)。 所以当main()想要调用foo() ,它首先必须调整堆栈指针。


主要的前三行

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

被称为函数序言。 这组指令将基指针压入堆栈,然后为基指针分配当前堆栈的值,从而创建一个新的堆栈帧。 然后减少堆栈指针以为函数的局部变量保留空间(您没有,但由于调用约定仍然完成)。 下一条指令

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

将堆栈与下一个较低的16字节边界对齐。 以下说明

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

已经在SE上出现了几次(这里,正如Paul R所指出的,在这里,以及在这里)。 这个例程似乎在堆栈上预留了额外的空间,但是却以一种奇怪无效的方式进行。 这部分可能取决于gcc版本和操作系统,似乎没有必要。

其余指令调用foo并退出程序。

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

上一篇: Stack contents during a function call

下一篇: based virtual machine function call/return implementation issues