问题 在c中执行x86函数调用后会恢复哪些寄存器?


我在x86程序集中编写一个函数,应该可以从c代码中调用,我想知道在返回调用者之前我必须恢复哪些寄存器。 目前我只恢复esp和ebp,而返回值是eax。 还有其他我应该关注的寄存器,还是我可以留下任何令我高兴的东西?


12402
2018-03-07 14:09


起源

没有一般规则 - 您必须查阅C编译器的文档以了解它的期望。 - Jerry Coffin
我很确定Jerry是对的,这取决于召唤惯例;如果内存服务,在Windows,Posix等上有不同的“标准”约定。您使用哪种编译器? - Tomer Gabel
GCC。我找到了这个搜索 en.wikibooks.org/wiki/X86_Disassembly/Calling_Conventions (请参阅退出序列),但它没有说明寄存器,只是它们应该恢复到调用者期望的状态。 - bobbaluba


答案:


运用 微软的32位ABIEAXEDX 和 ECX 是临时寄存器,其他一切都必须保留。

对于Windows下的x64, 微软说 你只需要恢复 RBXRBPRDIRSIR12R13R14,和 R15

对于x64下面的任何内容 System V和AMD64(见图3.4), 它的 RBPRBXRSPR12R13R14,和 R15 (它们看起来很奇怪,因为内核使用一组寄存器而userland代码使用另一组,这在ABI文档的附录A中列出)。


9
2018-03-07 14:43





32-bit: EBX, ESI, EDI, EBP
64-bit Windows: RBX, RSI, RDI, RBP, R12-R15, XMM6-XMM15
64-bit Linux,BSD,Mac: RBX, RBP, R12-R15

详情见“软件优化资源“通过Agner Fog。调用约定在 这个pdf


6
2018-03-07 14:30



别忘了RSP =) - Stephen Canon
@StephenCanon和EIP / RIP :) - Evgeny Kluev
你知道吗,我也会指出这一点,但是 ret 指令确实为您处理指令指针。 - Stephen Canon
+1指向Agner Fog关于优化和调用约定的资源的链接。确实是一个非常有用的信息来源。 - Eugene


如果您不确定寄存器的情况,下面的这些说明可以轻松地节省一天。

PUSHA / PUSHAD - 推送所有通用寄存器
POPA / POPAD - 弹出所有一般登记册

这些指令按一定顺序推送和弹出通用和SI / ESI,DI / EDI寄存器。

PUSHA / PUSHAD指令的顺序如下。

Opcode  Instruction  Clocks   Description

60      PUSHA        18       Push AX, CX, DX, BX, original SP, BP, SI, and DI
60      PUSHAD       18       Push EAX, ECX, EDX, EBX, original ESP, EBP ESI, and EDI

POPA / POPAD指令的顺序如下。 (按相反顺序)

Opcode   Instruction   Clocks   Description

61       POPA          24       Pop DI, SI, BP, SP, BX, DX, CX, and AX
61       POPAD         24       Pop EDI, ESI, EBP, ESP(***),EBX, EDX, ECX, and EAX

*** ESP值被丢弃而不是加载到ESP中。


1
2017-08-09 20:26



该 POPA 和 POPAD 指令实际上不会弹出(E)SP寄存器!还请更正错误 POPAD:你忘记了EBX寄存器。此外,你错误地说这些说明触及了 段寄存器! - Sep Roland