STATCK SEGMENT STATCK
STL DW 100H DUP(?)
STATCK ENDS
CODE SEGMENT
ASSUME CS:CODE,SS:STATCK
STATCK:MOV AX,STATCK
MOV SS,AX
MOV SP,SIZE STL
MOV AX,6789H
MOV BX,1234H
PUSH AX
PUSH BX
ADD AX,BX
POP AX
POP BX
AND AX,BX
MOV AH,4CH
INT 21H
CODE ENDS
END STATCK
堆栈指针寄存器SP的初值是多少?执行PUSH AX命令后,SP的值是多少?执行POP BX后,SP的值是多少?为什么答案给的是200,202,200。
MOV SS,AX ; 将 STATCK 段的地址装入 SS
MOV SP, SIZE STL ; 将 STL 段的大小装入 SP
STL DW 100H DUP(?)
定义了 100H 个字的堆栈空间,SIZE STL
表示 STL
的大小为 100H
个字。SP
时,会给出一个字地址。因此,SIZE STL
的值为 100H,但它在段中的字节总数是 200H(因为一个字 = 2 字节)。SP
是基于字节的指针。这样,初始化后的 SP
值为 200H,表示堆栈的顶端。PUSH AX
PUSH
操作会将数据压入堆栈,堆栈从高地址向低地址增长。
SP
初始值为 200H。PUSH AX
操作会将堆栈指针 SP
减少 2(因为 AX
是 16 位寄存器,占 2 个字节),然后将 AX
的值存入由新 SP
指向的位置。因此,PUSH AX
执行后:
SP
= 200H - 2 = 1FEH。接下来再执行 PUSH BX
:
PUSH BX
同理,SP
再次减少 2,因为 BX
同样是一个 16 位寄存器。
SP
的值为 1FEH。PUSH BX
后,SP
= 1FEH - 2 = 1FCH。接下来执行 POP AX
:
POP AX
POP
操作会将堆栈顶的 16 位数据弹出到 AX
中,并将 SP
增加 2。
SP
的值是 1FCH。POP AX
后,SP
= 1FCH + 2 = 1FEH。POP BX
最后执行 POP BX
:
SP
再增加 2。POP BX
后,SP
= 1FEH + 2 = 200H。整个过程中的 SP
变化如下:
所以,之前的错误在于没有理解堆栈指针的变化过程,实际上 PUSH AX
后 SP
为 1FEH 而不是 202H。
如果你遇到 202H 的值,可能是因为代码环境与段寄存器或指针计算方式的差异(如字节级别的推断),但在经典的 x86 模式下,应该是 1FEH。