【问题标题】:Stack frame creation in 64 bit machine在 64 位机器中创建堆栈帧
【发布时间】:2015-09-18 04:25:48
【问题描述】:

我只是在学习一些程序的低级分析。在使用gcc进行32位编译时,发现栈帧的创建顺序如下:

  1. 以相反的顺序推送函数参数。
  2. 保存退货地址
  3. 保存帧指针
  4. 创建局部变量

所以参数的地址应该是最高的,因为堆栈以相反的顺序增长。但是当我尝试使用 64 位编译时,我无法理解它是如何创建的,这与我在 32 位编译中发现的相反。这是代码和内存详细信息:

void test(int a, int b, int c, int d)
{
    int flag;
    char buf[10];
    num = 100;
}

int main()
{
        test(1, 2, 3, 4);
}

现在为简单起见,我们只取参数和返回地址。

32 位编译:

0xffffd130: 0x00000001  0xffffd1f4  0xffffd1fc  0xf7e3ad1d
0xffffd140: 0xffffd158  0x0804842d  0x00000001  0x00000002
0xffffd150: 0x00000003  0x00000004  0x00000000  0xf7e22933
0xffffd160: 0x00000001  0xffffd1f4  0xffffd1fc  0xf7fdb6b0


   0x08048421 <+30>:    mov    DWORD PTR [esp],0x1
   0x08048428 <+37>:    call   0x80483f0 <test>
   0x0804842d <+42>:    leave  

这里一切正常。我可以在较高地址看到参数,紧接着是较低地址的返回地址0x0804842d。现在,

64位编译:

0x7fffffffdf80: 0x00000004  0x00000003  0x00000002  0x00000001
0x7fffffffdf90: 0x00400530  0x00000000  0x00400400  0x00000000
0x7fffffffdfa0: 0xffffdfb0  0x00007fff  0x0040052a  0x00000000
0x7fffffffdfb0: 0x00000000  0x00000000  0xf7a3baf5  0x00007fff

   0x0000000000400525 <+24>:    call   0x4004f0 <test>
   0x000000000040052a <+29>:    pop    rbp
   0x000000000040052b <+30>:    ret    

在这里我可以看到参数位于较低的地址,而返回地址0x0040052a 位于较高的地址。这里有什么问题?堆栈是否以相反的方向增长(从低到高地址)或堆栈帧的创建与上述顺序不同?请帮我理解。谢谢。

【问题讨论】:

标签: c assembly gcc x86-64 stack-memory


【解决方案1】:

在 x86-64 上,传递参数的标准方式是通过使用寄存器,而不是堆栈(除非您获得超过 6 个)。见http://www.x86-64.org/documentation/abi.pdf

我强烈建议在没有先阅读适当的文档(比如我刚刚链接的那个)之前不要进行任何类型的实验。

无论如何,如果你反汇编 main,你可以很容易地看到参数没有在堆栈上传递:

   0x0000000000400509 <+0>: push   %rbp
   0x000000000040050a <+1>: mov    %rsp,%rbp
   0x000000000040050d <+4>: mov    $0x4,%ecx
   0x0000000000400512 <+9>: mov    $0x3,%edx
   0x0000000000400517 <+14>:    mov    $0x2,%esi
   0x000000000040051c <+19>:    mov    $0x1,%edi
   0x0000000000400521 <+24>:    callq  0x4004f0 <test>
   0x0000000000400526 <+29>:    pop    %rbp
   0x0000000000400527 <+30>:    retq   

您还可以在测试中看到它们是如何进入堆栈的:

   0x00000000004004f0 <+0>: push   %rbp
   0x00000000004004f1 <+1>: mov    %rsp,%rbp
   0x00000000004004f4 <+4>: mov    %edi,-0x14(%rbp)
   0x00000000004004f7 <+7>: mov    %esi,-0x18(%rbp)
   0x00000000004004fa <+10>:    mov    %edx,-0x1c(%rbp)
   0x00000000004004fd <+13>:    mov    %ecx,-0x20(%rbp)
   0x0000000000400500 <+16>:    movl   $0x64,-0x4(%rbp)
   0x0000000000400507 <+23>:    pop    %rbp
   0x0000000000400508 <+24>:    retq   

【讨论】:

  • 谢谢。这就是我缺少的一点。也感谢您的链接.. :)
猜你喜欢
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
  • 2012-10-08
  • 1970-01-01
  • 1970-01-01
  • 2016-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多