我正在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个字节的影子空间,以供被调用方使用,无论是否有不适合寄存器的arg。)xmm6..15被保留。
有关更多详细信息,请参见https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention。
其他OS使用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/