程序集弹出一个空堆栈

时间:2015-10-05 07:51:35

标签: assembly x86

我正在学习汇编并想知道当你弹出一个空堆栈或增加SP(堆栈指针)时它发生了什么,例如它已经是FFFE:

seg1 segment 
       org 100h 
       pop ax
       mov ah,4ch 
       int 21h
seg1 ends

当我通过调试器运行程序时,我看到SP在执行pop命令后将指向SP = 0000。为什么SP指向0000?是因为内存中的最大SP是FFFF而它只是循环到第一个点? (我知道SP只会增加或减少2,因为push和pop总是2字节) 当命令执行时,程序是否会在SP = 0000处弹出任意对象?

我正在使用a86宏汇编程序,Oracle VM VirtualBox。 谢谢。

3 个答案:

答案 0 :(得分:4)

此效果称为"环绕"。 FFFE加2将是10000,但第一位只是被切掉,所以结果是0000。

这对签名操作很有用:FFFE相当于-2。 -2 + 2 = 0。

是的,下一个pop将加载SS:0000的值并递增SP,而push也会导致回绕并将值存储在SS:FFFE。

答案 1 :(得分:3)

SP是16位寄存器。

当您使用POP时,SP有" 2"添加到它。 FFFE + 2产生值0。

这种情况在旧架构(例如,X8086)上可能没有错误发生 在x86-32中运行16位实模式(我必须检查手册)。虽然它确实发生了,你应该认为这是编程错误,因为它违反了堆栈指针的意图,线性扫描堆栈区域。

在受保护模式下的x86-32或-64上,堆栈区域边缘的下降通常会产生非法的内存访问,由操作系统非常小心地标记超出有效堆栈的区域是"无效& #34;

答案 2 :(得分:2)

你应该真的养成查阅CPU文档的习惯。应该都在那里。

简而言之,在16位和32位CPU模式下,push和pop通常不太关心堆栈指针寄存器的值,以便递增或递减。寄存器值简单地包围0,与向任何其他通用寄存器添加或减去值的方式相同。唯一重要的是在访问堆栈存储器时堆栈指针寄存器中的地址是否在堆栈段限制内。在实模式中,似乎是这种情况,所有段都具有64KB的大小,并且从0到0xFFFF的所有偏移都是有效的。因此,如果您的SP始终正确对齐(即,它是2的倍数),则推送或弹出单个16位字不应该导致任何问题。但是,您应该记住,在实模式下,当前堆栈由中断服务程序使用,并且您应始终有足够的空间(除非您在禁用中断的情况下进行操作)。你应该记住,代码中的错误可能会使堆栈指针指向程序的代码或数据,从而破坏它。