Pet*_*des 10
ESP被中断隐式地异步使用.在现代操作系统中,它仅适用于内核堆栈,而不适用于用户空间堆栈.内核代码总是需要在启用中断时保持ESP有效,并假设在每条指令之后它下面的空间都被破坏了.
在用户空间中主要(仅?)异步使用ESP是信号处理程序,因此没有信号处理程序的进程不应该异步使用ESP.(你甚至可以为内核设计一个新的ABI,以提供不强制使用ESP的信号).
因此,在某些情况下,用户空间代码可以在关键循环中使用ESP作为第8个GP寄存器,否则必须泄漏某些内容,但正如该文章指出的那样,它使得调试在SEH想要查找的Windows上不太方便有效的堆栈.使用MMX或XMM寄存器来保存/恢复ESP,因为静态存储不是线程安全的,并且堆栈不可用(鸡/蛋问题).理论上的相同论点适用于在64位代码中使用RSP,但除RSP之外的15个reg,并且保证SSE2支持,使得这极不可能值得.
此答案中的其他所有内容同样适用于64位模式下的RSP.
ESP无法做到的只有一件事就是其他寄存器: ESP不能成为寻址模式下的索引寄存器.
mov edx, [esp + eax*4] ; legal
mov edx, [eax + esp*4] ; not encodeable
mov edx, [eax + esp] ; assemblers will encode this with esp as the base reg, since neither reg is scaled.
Run Code Online (Sandbox Code Playgroud)
如果我没记错的话,这是ESP just plain作为操作数不可用的唯一情况.另一个特例是ESP作为基址寄存器总是需要一个SIB字节,即使没有索引:
mov edx, [eax] ; 2 bytes: opcode + ModRM
mov edx, [ebp] ; 3 bytes: opcode + ModRM + disp8=0 (the other addressing-mode limitation, ebp/rbp and r13 as a base reg needs a displacement; the mode+M encoding that would mean this actually mean something else)
mov edx, [esp] ; 3 bytes: opcode + ModRM + SIB
mov edx, [ebp + 4] ; 3 bytes: opcode + ModRM + disp8
mov edx, [esp + 4] ; 4 bytes: opcode + ModRM + SIB + disp8
mov edx, [ebp + 4 + eax] ; 4 bytes: opcode + ModRM + SIB + disp8
mov edx, [esp + 4 + eax] ; 4 bytes: opcode + ModRM + SIB + disp8
Run Code Online (Sandbox Code Playgroud)
值得指出的是,即使与ECX等其他寄存器相比,EAX也有很多特别之处.例如,它是隐含使用stos,cdq并且用作一个操作数mul(这列表不是穷举).还有一个1字节的编码xchg eax, reg (非常适合代码高尔夫,但不是性能!),以及使用imm32(如add eax, imm32vs. add r/m32, imm32)的常见ALU操作.(在线查看这些ALU说明或英特尔指令参考手册的原始PDF - 请参阅x86标签wiki以获取链接.)
基本8个通用寄存器中唯一一个非"特殊"或由任何通用指令隐式使用的是EBX.有关x86寄存器及其名称来自/传统用途的更多信息,请访问http://www.swansontec.com/sregisters.html