x86 函数必须保留哪些寄存器? [英] What registers must be preserved by an x86 function?
问题描述
我正在用 x86 程序集编写一个应该可以从 c 代码调用的函数,我想知道在返回调用者之前必须恢复哪些寄存器.
I'm writing a function in x86 assembly that should be callable from c code, and I'm wondering which registers i have to restore before i return to the caller.
目前我只恢复esp
和ebp
,返回值在eax
.
Currently I'm only restoring esp
and ebp
, while the return value is in eax
.
是否还有其他我应该关注的寄存器,或者我可以在其中保留任何我喜欢的内容?
Are there any other registers I should be concerned about, or could I leave whatever pleases me in them?
推荐答案
使用 Microsoft 的32 位 ABI(cdecl
或 stdcall
或其他调用约定)、EAX
、EDX
和 ECX
是临时寄存器(调用破坏).其他通用整数寄存器是调用保留的.
Using Microsoft's 32 bit ABI (cdecl
or stdcall
or other calling conventions), EAX
, EDX
and ECX
are scratch registers (call clobbered). The other general-purpose integer registers are call-preserved.
EFLAGS 中的条件代码是调用破坏的.调用/返回时需要 DF=0,因此您可以先使用 rep movsb
而无需 cld
.x87 堆栈在调用时或从不返回 FP 值的函数返回时必须为空.(FP 返回值在 st0
中,除此之外 x87 堆栈为空.)XMM6 和 7 是调用保留的,其余是调用破坏的暂存寄存器.
The condition codes in EFLAGS are call-clobbered. DF=0 is required on call/return so you can use rep movsb
without a cld
first. The x87 stack must be empty on call, or on return from a function that doesn't return an FP value. (FP return values go in st0
, with the x87 stack empty other than that.) XMM6 and 7 are call-preserved, the rest are call-clobbered scratch registers.
在 Windows 之外,大多数 32 位调用约定(包括 Linux 上的 i386 System V)都同意选择 EAX、EDX 和 ECX 作为调用破坏,但是所有xmm 寄存器都是调用- 惨败.
Outside of Windows, most 32-bit calling conventions (including i386 System V on Linux) agree with this choice of EAX, EDX and ECX as call-clobbered, but all the xmm registers are call-clobbered.
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.
For x64 under Windows, you only need to restore RBX
, RBP
, RDI
, RSI
, R12
, R13
, R14
, and R15
. XMM6..15 are call-preserved. (And you have to reserve 32 bytes of shadow space for use by the callee, whether or not there are any args that don't fit in registers.) xmm6..15 are call-preserved.
See https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention for more details.
其他操作系统使用 x86-64 System V ABI(见图 3.4),其中调用保留的整数寄存器为RBP
、RBX
、RSP
、R12
,R13
、R14
和 R15
.所有 XMM/YMM/ZMM 寄存器都被调用破坏了.
Other OSes use the x86-64 System V ABI (see figure 3.4), where the call-preserved integer registers are RBP
, RBX
, RSP
, R12
, R13
, R14
, and R15
. All the XMM/YMM/ZMM registers are call-clobbered.
EFLAGS 和 x87 堆栈与 32 位约定中的相同:DF=0,条件标志被破坏,x87 堆栈为空.(x86-64 约定在 XMM0 中返回 FP 值,因此 x87 堆栈寄存器总是在调用/返回时需要为空.)
EFLAGS and the x87 stack are the same as in 32-bit conventions: DF=0, condition flags are clobbered, and x87 stack is empty. (x86-64 conventions return FP values in XMM0, so the x87 stack registers always need to be empty on call/return.)
有关官方调用约定文档的链接,请参阅https://stackoverflow.com/tags/x86/info
For links to official calling convention docs, see https://stackoverflow.com/tags/x86/info
这篇关于x86 函数必须保留哪些寄存器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!