例题
代码语言:javascript复制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。
解析如下
1. SP 的初始值为 200H 的原因
代码语言:javascript复制MOV SS,AX ; 将 STATCK 段的地址装入 SS
MOV SP, SIZE STL ; 将 STL 段的大小装入 SP
STL DW 100H DUP(?)
定义了 100H 个字的堆栈空间,SIZE STL
表示STL
的大小为100H
个字。- 堆栈段是基于 字(Word,16 位)而不是字节计算的,且初始化
SP
时,会给出一个字地址。因此,SIZE STL
的值为 100H,但它在段中的字节总数是 200H(因为一个字 = 2 字节)。 - 在汇编的段模式下,
SP
是基于字节的指针。这样,初始化后的SP
值为 200H,表示堆栈的顶端。
2. PUSH AX 后的 SP 值
代码语言:javascript复制PUSH AX
PUSH
操作会将数据压入堆栈,堆栈从高地址向低地址增长。
- 堆栈指针
SP
初始值为 200H。 PUSH AX
操作会将堆栈指针SP
减少 2(因为AX
是 16 位寄存器,占 2 个字节),然后将AX
的值存入由新SP
指向的位置。
因此,PUSH AX
执行后:
SP
= 200H - 2 = 1FEH。
3. PUSH BX 后的 SP 值
接下来再执行 PUSH BX
:
PUSH BX
同理,SP
再次减少 2,因为 BX
同样是一个 16 位寄存器。
- 此时
SP
的值为 1FEH。 - 执行
PUSH BX
后,SP
= 1FEH - 2 = 1FCH。
4. POP AX 后的 SP 值
接下来执行 POP AX
:
POP AX
POP
操作会将堆栈顶的 16 位数据弹出到 AX
中,并将 SP
增加 2。
- 此时
SP
的值是 1FCH。 - 执行
POP AX
后,SP
= 1FCH 2 = 1FEH。
5. POP BX 后的 SP 值
代码语言:javascript复制POP BX
最后执行 POP BX
:
SP
再增加 2。- 执行
POP BX
后,SP
= 1FEH 2 = 200H。
总结
整个过程中的 SP
变化如下:
- SP 初始值: 200H
- 执行 PUSH AX 后: 1FEH
- 执行 PUSH BX 后: 1FCH
- 执行 POP AX 后: 1FEH
- 执行 POP BX 后: 200H
所以,之前的错误在于没有理解堆栈指针的变化过程,实际上 PUSH AX
后 SP
为 1FEH 而不是 202H。
如果你遇到 202H 的值,可能是因为代码环境与段寄存器或指针计算方式的差异(如字节级别的推断),但在经典的 x86 模式下,应该是 1FEH。