如何修复DOSBox 0.74中tempTotal溢出引发的Relative jump of range by 0001h错误?
问题修复方案
问题根源
- 变量溢出:
tempTotal定义为DB(8位字节型),三个字节变量相加的总和可能超过255(8位无符号数最大值),导致AL寄存器溢出,结果被截断,同时ADD指令会置位溢出标志OF=1。若后续代码存在依赖OF的跳转指令(如JO),可能因跳转范围超出短跳转(-128~+127字节)限制,触发“Relative jump of range by 0001h bytes”错误。 - 显示逻辑错误:
AAM指令仅能处理AL中0~99的二进制数,将其转换为非压缩BCD码。若AL因溢出被截断或原值超过99,AAM生成的AH会大于9,加上3030H后得到的ASCII码并非数字字符,导致显示异常。
修复步骤
1. 扩展变量存储宽度
将tempTotal改为16位字变量(DW),避免8位溢出:
temp DB ? ; remainder DB ? ; quotient DB ? ; tempRebate DB ? ; tempSST DB ? ; tempTotal DW ? ; 改为16位变量,支持最大65535的数值
2. 调整累加逻辑,处理进位
使用16位寄存器AX累加,同时处理8位相加产生的进位:
MOV AX, 0 ; 初始化AX为0 MOV AL, totalPrice ; 加载第一个数值到AL ADD AL, tempRebate ; 累加第二个数值 ADC AH, 0 ; 将加法产生的进位加到AH MOV BL, tempSST ; 加载第三个数值到BL ADD AL, BL ; 累加第三个数值 ADC AH, 0 ; 再次处理进位 MOV tempTotal, AX ; 保存16位总和
3. 修改显示逻辑,适配16位数值
由于总和可能是三位数(最大255*3=765),可以通过除法拆分每一位后依次显示:
MOV AX, tempTotal ; 加载16位总和到AX ; 打印百位 MOV BL, 100 DIV BL ; AL=百位,AH=余数(十位+个位) ADD AL, 30H ; 转换为ASCII字符 MOV DL, AL MOV AH, 02H INT 21H ; DOS调用显示字符 ; 打印十位和个位 MOV AL, AH ; 将余数加载到AL MOV AH, 0 AAM ; 转换为非压缩BCD码(AH=十位,AL=个位) ADD AX, 3030H ; 转换为ASCII字符 PUSH AX MOV DL, AH INT 21H ; 显示十位 POP DX MOV AH, 02H INT 21H ; 显示个位
额外优化建议
- 若不需要保留总和变量,可直接用
AX完成累加和显示,省略tempTotal,节省内存。 - 可在累加后添加溢出检查逻辑,如用
JO指令跳转到错误提示代码,避免执行异常显示流程:
JO OverflowHandler ; 若溢出则跳转到错误处理 ; ... 正常显示代码 ... OverflowHandler: MOV DL, 'O' MOV AH, 02H INT 21H MOV DL, 'V' INT 21H MOV DL, 'E' INT 21H MOV DL, 'R' INT 21H MOV DL, 'F' INT 21H MOV DL, 'L' INT 21H MOV DL, 'O' INT 21H MOV DL, 'W' INT 21H ; 后续退出或处理逻辑
内容的提问来源于stack exchange,提问作者Laoshen老绅
相关产品推荐
相关产品推荐

