【问题标题】:At what position in the stack should the preserved registers be saved when calling a function?调用函数时应将保留的寄存器保存在堆栈中的哪个位置?
【发布时间】:2018-02-25 05:20:47
【问题描述】:

根据调用约定,调用函数时,调用者必须保留一些寄存器,而被调用者必须保留其他寄存器。

现在我试图了解应将保留的寄存器保存在堆栈中的哪个位置。

这是我认为正确的位置:

【问题讨论】:

  • 如果您的函数不是可重入的,您甚至可以将它们保存在static 存储中的某个地方。 (你可以,但不要。没有优势,我只是指出这一点是为了强调你的函数拥有 args 上方的堆栈空间,并且对 如何 你安排返回没有要求保留调用的寄存器保持其原始值..)

标签: assembly x86


【解决方案1】:

术语“调用者保存的寄存器”并不意味着调用者必须保存它们;这意味着调用者在调用后不能指望它们具有任何合理的值,因此如果调用者关心这些值,它必须保存它们。

调用者可能决定保存所有、部分或不保存调用者保存的寄存器。因此,他们必须任何属于实际函数调用过程的一部分(参数和返回地址)。

同样,被调用者需要存储ebp 或被调用者保存寄存器;它只需要确保它们在返回时具有相同的价值。如果它从不使用它们,那么就没有理由保存它们。

调用约定中唯一真正不可变的部分是参数、返回地址、哪些寄存器是被调用者保存的,以及返回值的方式。这些定义了一个函数如何与另一个函数交互,如果你改变了,没有人会知道如何调用你的函数/被调用的函数不知道它需要什么。对于其他一切,编译器可以而且可能会做任何它认为方便的事情,你也可以。

【讨论】:

  • "call-preserved" vs. "call-clobbered" 是避免调用者或被调用者必须保存任何内容的好方法。 (并且该术语更清楚地映射到您在为需要或不需要在函数调用中生存的事物分配 reg 时的实际想法)。
  • 你提到了args,但是调用者和被调用者也必须就如何返回值达成一致。在不同的 ABI 中,按值返回结构的处理方式不同。例如,有些总是传递隐藏指针,但 x86-64 System V 会将最多 16 字节的小结构打包到 rdx:rax 中。浮点返回值在某些 ABI 中位于 xmm0 中,但在其他 ABI 中位于 st(0) 中。幸运的是,在所有调用约定中,整数/指针返回值始终位于 eax / rax 中。有关 ABI 文档的链接,请参阅 x86 tag wiki。也许提到返回值,或者不提到:P
猜你喜欢
  • 2011-10-15
  • 2015-03-26
  • 1970-01-01
  • 2012-03-25
  • 2016-12-06
  • 1970-01-01
  • 2018-06-17
相关资源
最近更新 更多