通过linux x86-64函数调用保留了哪些寄存器?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (393)

我相信我理解linux x86-64 ABI如何使用寄存器和堆栈将参数传递给函数(参见之前的ABI讨论)。我感到困惑的是,在函数调用中是否预期保留了哪些寄存器。也就是说,哪些寄存器被保证不被破坏?

提问于
用户回答回答于

以下是文档[ PDF链接 ]中完整的寄存器表及其用法:

r12r13r14r15rbxrsprbp是被调用方保存的寄存器-他们在“腌制在函数调用”一栏有一个“是”。

用户回答回答于

ABI指定允许一个符合标准的软件。它主要是为编译器,链接器和其他语言处理软件的作者编写的。这些作者希望他们的编译器能够生成能够与由相同(或不同)编译器编译的代码一起正常工作的代码。它们都必须同意一组规则:函数的形式参数如何从调用者传递给被调用者,函数返回值如何从被调用者传递回调用者,哪些寄存器在调用边界上保留/暂存/未定义,等等上。

例如,一条规则声明生成的函数汇编代码必须在更改值之前保存保留寄存器的值,并且代码必须在返回其调用者之前恢复保存的值。对于临时寄存器,生成的代码不需要保存和恢复寄存器值; 如果需要,它可以这样做,但不允许符合标准的软件依赖于这种行为(如果它不是符合标准的软件)。

如果您正在编写汇编代码,则负责按照相同的规则进行播放(您正在扮演编译器的角色)。也就是说,如果您的代码更改了被调用者保留的寄存器,则您负责插入保存和恢复原始寄存器值的指令。如果汇编代码调用外部函数,则代码必须以符合标准的方式传递参数,并且它可以取决于当被调用者返回时保留的寄存器值实际上被保留的事实。

规则定义了符合标准的软件如何相处。然而,这是完全合法的编写(或生成)的代码,而不是通过这些规则玩!编译器一直这样做,因为他们知道在某些情况下不需要遵循规则。

例如,考虑一个名为foo的C函数,声明如下:

static foo(int x);

在编译时,编译器100%确定此函数只能由当前正在编译的文件中的其他代码调用。foo考虑到静态意义的定义,函数不能被任何其他东西调用。因为编译器在编译时知道所有调用者foo,所以编译器可以自由地使用它想要的任何调用序列(直到并且包括不进行调用,即将代码内联foo到调用者中foo

作为汇编代码的作者,您也可以这样做。也就是说,只要该协议不会干扰或违反符合标准的软件的期望,您就可以在两个或更多例程之间实现“私有协议”。

扫码关注云+社区

领取腾讯云代金券