ESP 和 EAX 一样通用吗?

Is ESP as general-purpose as EAX?

在x86架构下,有什么是EAX能做到而ESP不能做到的?忘记 pushpopcall

ESP 被中断隐式异步使用。在现代操作系统中,这仅适用于内核堆栈,不适用于 user-space 堆栈。内核代码始终需要在启用中断时保持 ESP 有效,并假设它下面的 space 在每条指令后都被破坏。

user-space 中 ESP 的主要(唯一?)异步使用是信号处理程序,因此没有信号处理程序的进程不应该异步使用 ESP。 (内核甚至可以使用线程当前堆栈指针以外的堆栈向用户 space 传递信号,例如 POSIX sigaltstack,尽管如果使用 alt-stack 可以进行嵌套信号处理,信号处理程序代码不能假设任何东西)。请参阅 以更详细地了解 Windows 上的内容,其中 SEH 的特殊情况可能发生在任何地方,因此 通常 使用 [=64] 并不安全=]低于ESP。

此外,调试器 可以 在计算 print foo(1) 之类的东西时使用目标进程的堆栈来调用目标程序中的函数。 (但在现代多任务操作系统下,其他方面都是非侵入性的。)

所以用户-space 代码在某些情况下可以逃脱 using ESP as an 8th GP register in a critical loop 否则必须溢出一些东西,但正如那篇文章指出的那样,它使 [=61= 上的调试不那么方便] SEH 想要找到有效堆栈的地方。使用 MMX 或 XMM 寄存器到 save/restore ESP,因为静态存储不是线程安全的,并且堆栈不可用(chicken/egg 问题)。理论上相同的论点适用于在 64 位代码中使用 RSP,但 RSP 以外的 15 个 regs 和保证的 SSE2 支持使得这极不可能值得。

此答案中的所有其他内容同样适用于 64 位模式下的 RSP。


ASM/机器代码中作为 GP 寄存器操作数的 ESP 限制

只有一件事 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.

如果我没记错的话,这是 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

pop 进入 ESP 也有点特殊,因为读取隐式源、ESP 的隐式增量和写入显式目标之间的操作顺序很重要:pop esp 就像 mov esp, [esp]。 (此外,popa 跳过重新加载 ESP)。有关详细信息,请参阅 What is an assembly-level representation of pushl/popl %esp?


同样值得指出的是,即使与 ECX 等其他寄存器相比,EAX 也有很多特别之处。例如,它隐含地与 stoscdq 一起使用,并作为 mul 的操作数(此列表并不详尽)。 xchg eax, reg (great for code golf but not performance!), and for the common ALU operation with an imm32 (like add eax, imm32 vs. add r/m32, imm32). (Look up these ALU instructions online or the original PDF of Intel's instruction reference manual—see the 标签 wiki 链接也有一个 1 字节编码。)

EBX 是 8 进制通用寄存器中唯一不“特殊”或不被任何通用指令隐式使用的寄存器。有关 x86 寄存器及其名称来源/传统用途的更多信息,请参阅 http://www.swansontec.com/sregisters.html