【发布时间】:2016-01-02 07:17:10
【问题描述】:
PUSH 到 FULL 堆栈的物理后果是什么 令人惊讶的是,当只为堆栈分配 2 个字节 [1 个字] 并 PUSH 三个字然后将它们弹出到不同的寄存器中时,它没有任何错误地完成 推送第二个项目时,我能对堆栈内容说些什么
这是堆栈段定义:
Stack_segment_name segment para stack
db 2 dup(0) ;define your stack segment
Stack_segment_name ends
代码如下:
Code_segment_name segment
Main_prog PROC FAR
assume SS:Stack_segment_name,CS:Code_segment_name,DS:Data_segment_name,ES:Data_segment_name
MOV AX,Data_segment_name ; load the starting address of the data
MOV DS,AX ; segment into DS reg.
MOV AX,1715H
MOV BX,1518H
MOV CX,2944H
PUSH AX
PUSH BX
PUSH CX
POP SI
POP DI
POP DX
MOV AH,4CH
INT 21H
Main_prog endp
Code_segment_name ends
end Main_prog
执行代码后:
SI=2944H
DI=1518H
DX=1715H
【问题讨论】:
-
8086 上的堆栈段(如 8086 上的所有段)为 64K。 SP(堆栈指针)是一个 16 位寄存器,因此如果/当您超过 64K 堆栈时,它会回绕。
-
好的,它会环绕,但这与实际程序的堆栈段定义中声明的 2 字节大小冲突。
-
汇编器中堆栈的大小不会转换为内存中相同的固定大小。所有物理段的大小都是 64k。您指定的大小是最小保证之前的字节数堆栈包装。因此,如果您指定一个包含 2 个字节的堆栈,则 SS 将自动设置为内存中 2 个字节所在段落的开头。 SP 将设置为堆栈的大小 - 在您的情况 2 中。因此,您最终会得到类似 SS:0002h 作为起始堆栈位置的东西。您推送的第一个单词将位于 SS:0000h,您推送的第二个单词将换行并放置在 SS:0fffeh
-
而我的cmets是在8086实模式下的。
-
我不认为你运行了你认为你运行的实验。我看不到您如何将堆栈指针设置为您声明的堆栈区域。我认为您的程序正在使用加载程序提供的堆栈区域运行,该堆栈区域通常很大。 (如果您确实将 SP 设置为您定义的区域,您的推送将覆盖超出其末尾的一些字节。如果这些字节对某些内容至关重要,您的程序将失败。如果不是,它将意外成功,这回答了您的原始问题)。见stackoverflow.com/a/34546569/120163