X86 堆栈指针寄存器是如何工作的

X86 堆栈指针寄存器是如何工作的,x86,stack-pointer,X86,Stack Pointer,那么,堆栈是如何工作的呢?例如,说明: push ax 等于: sub sp, 4 mov sp, ax 其中sp是堆栈指针。是这样吗 我的问题是-如果稍后我将sp寄存器中的4更改为完全不同的值,那么从sp寄存器中减去4又有什么意义呢?我想应该是这样的 mov [sp], ax 也就是说,将ax的值放入sp指向的内存中。我认为应该读取 mov [sp], ax 也就是说,将ax的值放入sp指向的内存。您正在将ax的值移动到下一个可用堆栈帧中。堆栈指针向下构建(因此,如果有太多的值,它将下

那么,堆栈是如何工作的呢?例如,说明:

push ax
等于:

sub sp, 4
mov sp, ax
其中sp是堆栈指针。是这样吗


我的问题是-如果稍后我将sp寄存器中的4更改为完全不同的值,那么从sp寄存器中减去4又有什么意义呢?

我想应该是这样的

mov [sp], ax

也就是说,将ax的值放入sp指向的内存中。

我认为应该读取

mov [sp], ax

也就是说,将ax的值放入sp指向的内存。

您正在将ax的值移动到下一个可用堆栈帧中。堆栈指针向下构建(因此,如果有太多的值,它将下溢超过零并引发错误,而不是溢出到重要的内容中),因此下一个可用堆栈帧位置是一个字(4字节)当前位置之前。

您正在将
ax的值移动到下一个可用堆栈帧中。堆栈指针向下构建(因此,如果有太多的值,它将下溢超过零并引发错误,而不是溢出到重要的内容中),因此下一个可用堆栈帧位置是当前位置之前的一个字(4字节)。

这不是推送ax
的工作方式。它“等于”的代码示例应为:

sub sp, 4 
mov [ss:sp], ax
您不会用AX覆盖SP的值。而是将AX复制到SS:SP指向的内存地址中(使用堆栈段,而不是数据段)。。。但事实上,这甚至不准确。你真正需要的是这样的东西:

mov [tmp], sp
pushf ;push flags
sub [tmp], 4
popf
mov sp, [tmp]
mov [ss:sp], ax
但事实上,即使这样也不完全准确。
mov sp,[tmp]
也会导致执行隐式
cli
(期望
mov ss,foobar
),这可能是不需要的


基本上,
push
做了一些非常简单的事情,但是这个简单事情的细节使得它非常值得自己编写指令

这不是推送ax的工作方式。它“等于”的代码示例应为:

sub sp, 4 
mov [ss:sp], ax
您不会用AX覆盖SP的值。而是将AX复制到SS:SP指向的内存地址中(使用堆栈段,而不是数据段)。。。但事实上,这甚至不准确。你真正需要的是这样的东西:

mov [tmp], sp
pushf ;push flags
sub [tmp], 4
popf
mov sp, [tmp]
mov [ss:sp], ax
但事实上,即使这样也不完全准确。
mov sp,[tmp]
也会导致执行隐式
cli
(期望
mov ss,foobar
),这可能是不需要的


基本上,
push
做了一些非常简单的事情,但是这个简单事情的细节使得它非常值得自己编写指令

不同之处在于
子esp,4
将设置标志,但push不会设置标志。另外,它应该是
mov[esp],eax
。您显示的16位版本表示您正在使用一本非常旧的书。再也没有人在16位机器上编程了(可能除了嵌入式微控制器)


在x86上,OF、SF、ZF、ZF、PF和CF标志将通过减法设置,但没有标志受
PUSH

的影响。区别在于
子esp,4
将设置标志,但PUSH不会设置标志。另外,它应该是
mov[esp],eax
。您显示的16位版本表示您正在使用一本非常旧的书。再也没有人在16位机器上编程了(可能除了嵌入式微控制器)


在x86上,OF、SF、ZF、ZF、PF和CF标志将通过减法设置,但任何标志都不受
推送的影响

在@Amadanon的答案上下文中阅读我的答案。:)在@Amadanon的答案中阅读我的答案。:)我想说的是,16位指令在进入32位指令之前更容易理解,特别是在SIMD寻址和保护模式等领域,以及所有初学者在开始时难以理解的东西。我想说,16位指令在进入32位指令之前更容易理解,特别是在SIMD寻址和保护模式等领域,以及所有初学者在开始时难以摸索的可能重复的