我正在 x86 程序集中编写一个函数,该函数应该可以从 C 代码调用,我想知道在返回调用者之前必须恢复哪些寄存器。
目前我只恢复esp
和ebp
,而返回值在eax
中。
还有其他我应该关心的寄存器吗?或者我可以在其中留下我喜欢的内容吗?
最佳答案
使用Microsoft's 32 bit ABI (cdecl
或 stdcall
或其他调用约定)、EAX
、EDX
和 ECX
是暂存寄存器(调用破坏)。其他通用整数寄存器是调用保留的。
EFLAGS 中的条件代码被调用破坏。调用/返回时需要 DF=0,因此您可以先使用 rep movsb
而无需使用 cld
。 x87 堆栈在调用时或从不返回 FP 值的函数返回时必须为空。 (FP 返回值位于 st0
中,除此之外 x87 堆栈为空。)XMM6 和 7 是调用保留的,其余的是调用破坏的暂存寄存器。
在 Windows 之外,大多数 32 位调用约定(包括 Linux 上的 i386 System V)都同意选择 EAX、EDX 和 ECX 作为调用破坏,但是所有 xmm 寄存器都被调用- 被破坏了。
<小时/>对于Windows下的x64,只需恢复RBX
、RBP
、RDI
、 RSI
、R12
、R13
、R14
和 R15
。 XMM6..15 是调用保留的。 (并且您必须保留 32 字节的影子空间供被调用者使用,无论是否有任何不适合寄存器的参数。) xmm6..15 是调用保留的。
请参阅https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention了解更多详情。
其他操作系统使用 x86-64 System V ABI (see figure 3.4) ,其中调用保留的整数寄存器为 RBP
、RBX
、RSP
、R12
、R13
、R14
和 R15
。所有 XMM/YMM/ZMM 寄存器都被调用破坏。
EFLAGS 和 x87 堆栈与 32 位约定相同:DF=0,条件标志被破坏,x87 堆栈为空。 (x86-64 约定在 XMM0 中返回 FP 值,因此 x87 堆栈寄存器在调用/返回时始终需要为空。)
<小时/>有关官方调用约定文档的链接,请参阅 https://stackoverflow.com/tags/x86/info
关于assembly - x86 函数必须保留哪些寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9603003/