我已经编写了自己的 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";" \
)
答案 0 :(得分:7)
你的指令序列没有保存flags register,它甚至可能在IA32中保存。维基百科页面包含可用于执行此操作的说明pushf
和popf
。
除非您知道程序不使用它们,否则您需要保存所有向量寄存器。注意:它们也可以用于标量浮点,因此您不需要在程序中使用矢量化代码即可使用它们。 哦,如果程序使用浮点数,您应该保存历史浮点堆栈以防万一。 Dan Kruchinin的答案显示了如何一步到位地保存所有这些。
答案 1 :(得分:4)
您可能需要使用fxsave / fxrestore说明保存x87上下文:http://siyobik.info/main/reference/instruction/FXSAVE
虽然,我不确定fxsave / fxresrtore是否可以安全地从用户空间应用程序中使用(即在管理员模式之外),但你可以自己完成fxsave所做的几乎所有事情。