函数调用说明说明

时间:2014-08-22 10:46:58

标签: c++ assembly x86

所以,我最近开始了解x86汇编语言。 我创建了以下C ++代码的目标文件,并使用objdump -S查看创建的.o文件。

void func(){
    int d,f;
    d=10;
    f=1;    
}

int main(){
    int x;
    x = 1;
}

我得到了以下汇编代码:

t1.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <_Z4funcv>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   c7 45 f8 0a 00 00 00    movl   $0xa,-0x8(%rbp)
   b:   c7 45 fc 01 00 00 00    movl   $0x1,-0x4(%rbp)
  12:   5d                      pop    %rbp
  13:   c3                      retq   

0000000000000014 <main>:
  14:   55                      push   %rbp
  15:   48 89 e5                mov    %rsp,%rbp
  18:   c7 45 fc 01 00 00 00    movl   $0x1,-0x4(%rbp)
  1f:   b8 00 00 00 00          mov    $0x0,%eax
  24:   5d                      pop    %rbp
  25:   c3                      retq

有人可以使用汇编代码指令做什么吗?我知道push和pop用于存储和从堆栈中删除。但是教学的确切用途是什么?

1 个答案:

答案 0 :(得分:3)

调用约定要求保留哪些寄存器,包括rbp。这意味着,如果您的函数想要将rbp用于其自身目的,则必须确保它在函数出口处保持与在函数入口处相同的值。实现此目的的便捷方法是pushpop

rbp用于什么?从历史上看,bp寄存器用于标记堆栈帧并访问局部变量和函数参数。其中一个原因是在旧的16位代码中,您无法相对于堆栈指针sp进行寻址。此外,了解堆栈帧边界可能有助于调试和堆栈展开。在32位和现在的64位代码中,您可以相对于堆栈指针进行寻址,并且调试由专门的调试信息辅助,即使没有帧指针也能正常工作。因此,通常的做法是禁用帧指针,有效地释放一个寄存器以供一般使用。此代码尚未在启用优化的情况下编译,这就是您使用rbp的原因。

好的,让我们看看发生了什么。如上所述,行0保存rbp。然后,行1将堆栈指针的当前值保存在那里,标记堆栈帧。行4b只是初始化您的两个变量。请注意,它们位于堆栈指针下的128字节红色区域中,x86-64 ABI允许您在不分配的情况下使用它。通常,您会看到sub rsp, size-of-locals种用于从堆栈中分配空间的指令。行12恢复rbp的原始值,最后行13返回给调用者。

main函数非常相似,唯一有趣的区别在于1f,它将0加载到eax。该寄存器用于将返回值传递回调用者。

这只是对调用约定主题的快速浏览。有关更深入的详细信息,请参阅相应的文档。

相关问题