Assembly 为什么在使用PUSH或POP指令时不鼓励使用ESP寄存器?

Assembly 为什么在使用PUSH或POP指令时不鼓励使用ESP寄存器?,assembly,x86,stack-pointer,Assembly,X86,Stack Pointer,我正在浏览C代码,其中我必须计算特定程序跟踪中使用的寄存器数量。每当遇到push或pop命令时,该代码忽略了存储ESP寄存器。我还参考了X86指令,其中写道“ESP,堆栈指针,不应使用”。为什么???它不应用作通用寄存器。请随意使用它作为堆栈指针,并适当小心。例如,您可以在带有“sub esp,…”指令的堆栈上为本地变量保留一些内存,但必须在ret指令之前恢复其原始值。ret指令不应用作通用寄存器。请随意使用它作为堆栈指针,并适当小心。例如,您可以在带有“sub esp,…”指令的堆栈上为本地变

我正在浏览C代码,其中我必须计算特定程序跟踪中使用的寄存器数量。每当遇到push或pop命令时,该代码忽略了存储ESP寄存器。我还参考了X86指令,其中写道“ESP,堆栈指针,不应使用”。为什么???

它不应用作通用寄存器。请随意使用它作为堆栈指针,并适当小心。例如,您可以在带有“sub esp,…”指令的堆栈上为本地变量保留一些内存,但必须在ret指令之前恢复其原始值。ret指令不应用作通用寄存器。请随意使用它作为堆栈指针,并适当小心。例如,您可以在带有“sub esp,…”指令的堆栈上为本地变量保留一些内存,但必须在x86上的ret指令

之前恢复其原始值,
esp
是堆栈指针。最初,在16位8088和8086处理器上,寄存器简称为
SP
,用于StackPointer。在386处理器中添加32位支持时,所有寄存器名中都添加了
E
前缀(表示“扩展”),因此它变成了
ESP
。在当前模式下,堆栈指针的位宽度始终与处理器的本机字大小相同。也就是说,如果在32位保护模式下执行,堆栈指针将为32位宽,并存储在
ESP
中。如果在16位实模式下执行,堆栈指针将为16位宽,并存储在
SP

x86体系结构的64位扩展(被称为AMD64、x86-64或x64)将寄存器扩展到64位,并添加了
R
前缀。因此,
RSP
寄存器包含堆栈指针,在长(64位)模式下执行时,堆栈指针的宽度为64位

尽管该寄存器在概念上类似于其他寄存器(
EAX
ECX
EDX
EBX
ESI
EDI
)和
EBP
),但它不能以等效方式使用。它仅用于保存堆栈指针,不能用作通用寄存器

不显式推送或弹出堆栈指针的原因是,这是由其他指令隐式完成的。事实上,
PUSH
POP
指令是操纵堆栈指针的指令,因为它们将内容推送到堆栈并弹出

在x86上,堆栈在内存中总是向下增长,因此
PUSH
将从堆栈指针中减去适当的字节数(根据操作数的大小),而
POP
将添加适当的字节数

和指令还隐式操作堆栈指针。您可以通过阅读英特尔x86体系结构手册找到更多详细信息。TagWiki中还有很多其他可用资源

只有在
ADD
SUB
指令中将
ESP
寄存器用作目标操作数时,才会看到它被显式操作。通过优化编译器、根据需要增加或减少堆栈指针以留出额外空间来存储值或清理堆栈,这些指针通常会插入到函数的序言和尾声中。它们的功能类似于
PUSH
POP
,不同之处在于它们可以具有一行中多个PUSH和POP的效果。例如:

push eax
push eax
push eax
push eax
...
pop  eax
pop  eax
pop  eax
pop  eax
可以简单地替换为:

sub esp, 16
...
add esp, 16

(假设您实际上没有尝试存储
EAX
的值,只是使用
PUSH
在堆栈上腾出空间)。

在x86上,
ESP
是堆栈指针。最初,在16位8088和8086处理器上,寄存器简称为
SP
,用于StackPointer。在386处理器中添加32位支持时,所有寄存器名中都添加了
E
前缀(表示“扩展”),因此它变成了
ESP
。在当前模式下,堆栈指针的位宽度始终与处理器的本机字大小相同。也就是说,如果在32位保护模式下执行,堆栈指针将为32位宽,并存储在
ESP
中。如果在16位实模式下执行,堆栈指针将为16位宽,并存储在
SP

x86体系结构的64位扩展(被称为AMD64、x86-64或x64)将寄存器扩展到64位,并添加了
R
前缀。因此,
RSP
寄存器包含堆栈指针,在长(64位)模式下执行时,堆栈指针的宽度为64位

尽管该寄存器在概念上类似于其他寄存器(
EAX
ECX
EDX
EBX
ESI
EDI
)和
EBP
),但它不能以等效方式使用。它仅用于保存堆栈指针,不能用作通用寄存器

不显式推送或弹出堆栈指针的原因是,这是由其他指令隐式完成的。事实上,
PUSH
POP
指令是操纵堆栈指针的指令,因为它们将内容推送到堆栈并弹出

在x86上,堆栈在内存中总是向下增长,因此
PUSH
将从堆栈指针中减去适当的字节数(根据操作数的大小),而
POP
将添加适当的字节数

和指令还隐式操作堆栈指针。您可以通过阅读英特尔x86体系结构手册找到更多详细信息。TagWiki中还有很多其他可用资源

您将看到
ESP
寄存器的唯一时间