You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何CALL指令执行后栈指针SP数值增加?16位实模式Bochs调试疑问

问题:CALL指令执行后SP未递减反而增加的疑惑

在Bochs中运行16位实模式汇编代码时,进入PRINTCHAR过程后BX的值为0x1002。按预期CALL指令应该递减SP并压入返回IP,但实际SP反而增加了2?以下是代码及寄存器转储信息。

汇编代码

[BITS 16]
[ORG 0x7c00]
START:
MOV     AX,     0x0FA0
MOV     SS,     AX  
MOV     AX,     0x1000
MOV     SP,     AX
MOV     BP,     AX
MOV     AX,     0x1F40
MOV     DS,     AX
MOV     AX,     0x2EE0
MOV     ES,     AX
STI
CALL PRINTCHAR
CLI
HLT
PRINTCHAR:
MOV     BX,     SP
HLT

寄存器转储

00014725614i[CPU0  ] WARNING: HLT instruction with IF=0!
04272480000p[WINGUI] >>PANIC<< POWER button turned off.
04272480000i[CPU0  ] CPU is in real mode (halted)
04272480000i[CPU0  ] CS.mode = 16 bit
04272480000i[CPU0  ] SS.mode = 16 bit
04272480000i[CPU0  ] EFER   = 0x00000000
04272480000i[CPU0  ] | EAX=00000e00  EBX=00001002  ECX=00090000  EDX=00000000
04272480000i[CPU0  ] | ESP=00001000  EBP=00001000  ESI=000e0000  EDI=0000ffac
04272480000i[CPU0  ] | IOPL=0 id vip vif ac vm rf nt of df if tf sf zf af pf cf
04272480000i[CPU0  ] | SEG sltr(index|ti|rpl)     base    limit G D
04272480000i[CPU0  ] |  CS:0000( 0004| 0|  0) 00000000 0000ffff 0 0
04272480000i[CPU0  ] |  DS:1f40( 0005| 0|  0) 0001f400 0000ffff 0 0
04272480000i[CPU0  ] |  SS:0fa0( 0005| 0|  0) 0000fa00 0000ffff 0 0
04272480000i[CPU0  ] |  ES:2ee0( 0005| 0|  0) 0002ee00 0000ffff 0 0
04272480000i[CPU0  ] |  FS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
04272480000i[CPU0  ] |  GS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
04272480000i[CPU0  ] | EIP=00007c1c (00007c1c)
04272480000i[CPU0  ] | CR0=0x60000010 CR2=0x00000000
04272480000i[CPU0  ] | CR3=0x00000000 CR4=0x00000000
04272480000i[CPU0  ] 0x0000000000007c1c>> mov bx, sp : 89E3

原因分析

首先明确x86 16位实模式下CALL近调用的标准行为:

  • SP先递减2(SP = SP - 2)
  • 将返回地址(CALL指令的下一条指令的IP)压入SS:SP指向的内存
  • 跳转到目标过程地址

针对你遇到的异常情况,可能的原因如下:

1. 寄存器转储时机误解

从转储最后一行0x0000000000007c1c>> mov bx, sp : 89E3可以看出,MOV BX,SP指令即将执行,而非已经执行完毕。此时转储中的EBX=00001002是之前操作留下的旧值,并非执行该指令后得到的SP当前值。当前实际的SP值为转储中的ESP=00001000,但这仍不符合CALL执行后的预期(应为0xFFFE),需要进一步验证。

2. Bochs模拟/调试显示异常

极少数情况下,模拟器的寄存器显示可能存在bug,或调试上下文切换导致值显示异常。可以通过以下方式验证:

  • 在PRINTCHAR中添加内存写入指令,将SP的值存入内存后查看实际内容:
    PRINTCHAR:
    MOV     BX,     SP
    MOV     [0x0000], BX  ; 将BX写入DS:0x0000,对应物理地址0x1F400
    HLT
    
  • 在Bochs中查看物理地址0x1F400的内容,确认SP的真实值。

3. 汇编器指令生成错误

检查汇编后的机器码,确认CALL PRINTCHAR是否被正确编译为16位近调用指令(操作码0xE8,后跟16位偏移)。若汇编器错误生成了其他指令,可能导致SP异常变化。


验证建议

  • 单步调试:使用Bochs的s命令单步执行代码,执行CALL PRINTCHAR后立即查看SP值,确认是否为预期的0xFFFE。
  • 检查栈内存:执行CALL后,查看SS:SP对应的物理地址(0xFA00 + 0xFFFE = 0x109FE),确认是否存储了返回IP(即CLI指令的地址)。

内容的提问来源于stack exchange,提问作者user1322654

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 21:34:52