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

汇编代码中变量值意外变更问题排查求助(基于QEMU虚拟机)

问题分析与解决思路

核心原因推测

从你描述的现象和代码来看,cmdsize 莫名被修改的概率最高的两个方向:

  1. BIOS中断的寄存器破坏副作用:实模式下BIOS中断(如int 0x10、int 0x16)不会保存所有通用寄存器,若你的代码依赖未被保护的寄存器,可能间接引发内存访问错误;
  2. 变量地址与系统预留内存重叠:实模式低地址内存(0x0000~0xFFFF)是BIOS数据区、中断向量表等系统预留区域,若cmdsize被定义在这些区域,会被BIOS操作意外覆盖。

具体排查与修复步骤

1. 修复寄存器保护问题

BIOS中断会修改部分寄存器,必须在调用前保存、调用后恢复,避免后续逻辑出错:

; 等待键盘输入前,保存所有通用寄存器到栈
push ax
push bx
push cx
push dx
push di

mov ah, 0
int 0x16

; 恢复寄存器
pop di
pop dx
pop cx
pop bx
pop ax

cmp al, 0x0D
je inputend

同时修改printChar函数,避免破坏bx寄存器(int 0x10 ah=0xe会用到bx指定页码):

printChar:
    push bx
    mov ah, 0x0e
    mov bh, 0  ; 强制指定视频页码为0,避免依赖BIOS默认值
    int 0x10
    pop bx
    ret

调用printChar前也记得保存ax(因为函数会修改ah):

mov ax, [cmdsize]
add al, 0x30
push ax
call printChar
pop ax

2. 检查并更换变量内存位置

若cmdsize被定义在低地址(如0x0000~0xFFFF),大概率和BIOS预留区冲突。解决方法:

  • 将变量移到0x07E00之后的内存(软盘引导扇区默认加载到0x7C00,0x7E00之后是安全区);
  • 或者直接使用高地址段,比如用org 0x1000指定代码加载基址,把变量放在这个段内;
  • 无调试器情况下,可手动打印cmdsize的物理地址验证:
; 打印cs:cmdsize的物理地址(示例逻辑)
mov ax, cs
mov dx, cmdsize
; 自行实现十六进制打印函数,输出ax:dx组合的物理地址

对比实模式内存映射表,确认地址不在BIOS预留区(如0x0040~0x005F是BIOS数据区,绝对不能用)。

3. 排除内存写入的潜在错误

虽然你注释了mov di,cx到mov [di],al的代码,但要确认cx的初始值是否合法。如果之前逻辑中cx未被正确初始化,即使注释写入代码,后续若有其他依赖cx的操作,仍可能间接影响内存访问。

内容的提问来源于stack exchange,提问作者SCP-1762

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 03:42:46