x86 64位中的额外寄存器

时间:2011-10-31 10:53:30

标签: c linux 64-bit x86

我已经编写了自己的 setjmp / longjmp ,符合我的需求,如下所示。我在32位系统上进行了测试,效果很好。为此目的,我保存并恢复寄存器eax,ebx,ecx,edi,esi,esp,ebp和eip。

但是,我知道,对于64位系统来说,这还不够。首先,我想我需要用rX替换寄存器eX。其次,我想我需要保存x86-64位中的8个额外寄存器,即r8,r9,r10,r11,r12,r13,r14,r15。这样就够了,还是我还需要做更多的事情?

#define MY_SETJMP(n) __asm__ __volatile__ ("movl %eax, regax"#n";" \
     "movl %ebx, regbx"#n";" \
     "movl %ecx, regcx"#n";" \
     "movl %edi, regdi"#n";" \
     "movl %esi, regsi"#n";" \
     "movl %esp, regsp"#n";" \
     "movl %ebp, regbp"#n";" \
     "call next"#n";" \
     "next"#n": pop regip"#n";" \
     "addl $6, regip"#n";" \
     )

#define MY_LONGJMP(n) __asm__ __volatile__ ("movl regax"#n", %eax;" \
     "movl regbx"#n", %ebx;" \
     "movl regcx"#n", %ecx;" \
     "movl regdi"#n", %edi;" \
     "movl regsi"#n", %esi;" \
     "movl regsp"#n", %esp;" \
     "movl regbp"#n", %ebp;" \
     "jmp *regip"#n";" \
     )

2 个答案:

答案 0 :(得分:7)

你的指令序列没有保存flags register,它甚至可能在IA32中保存。维基百科页面包含可用于执行此操作的说明pushfpopf

除非您知道程序不使用它们,否则您需要保存所有向量寄存器。注意:它们也可以用于标量浮点,因此您不需要在程序中使用矢量化代码即可使用它们。 哦,如果程序使用浮点数,您应该保存历史浮点堆栈以防万一。 Dan Kruchinin的答案显示了如何一步到位地保存所有这些。

答案 1 :(得分:4)

您可能需要使用fxsave / fxrestore说明保存x87上下文:http://siyobik.info/main/reference/instruction/FXSAVE

虽然,我不确定fxsave / fxresrtore是否可以安全地从用户空间应用程序中使用(即在管理员模式之外),但你可以自己完成fxsave所做的几乎所有事情。