如何避免8086汇编程序显示00-98偶数时陷入无限循环?
问题解答
1. 为何当前代码无法在98处停止?
当前代码的计数逻辑和终止判断完全混乱,核心问题有两点:
- 计数偏移错误:程序用
BL遍历段码表,但初始值设为03且每次ADD BL,2,只会访问奇数偏移的段码(对应数字3、5、7、9...),永远到不了数字8的段码FF(偏移8,偶数),导致CMP AL, FF永远不成立,JZ Foo2永远跳不到,直接陷入display_loop无限循环。 - 终止条件逻辑错误:即便侥幸进入
Foo2,程序取[CL]的段码后执行DEC AL,再判断AL是否等于FF——段码减1后不可能等于FF(除非段码是00,但表中没有),所以JZ Stop永远触发不了,最终会无限跳回Foo1循环。
另外,代码初始显示操作与段码遍历逻辑完全不匹配,根本无法按顺序显示00、02...98这些偶数。
2. 如何修改实现显示98后正确终止?
重新梳理计数逻辑,用**十位(MSB)+ 个位(LSB)**的计数器组合,配合正确的段码读取和终止判断:
JMP Start ; 段码表:数字0-9对应的7段码 DB 0FBh ; 0 DB 00Bh ; 1 DB 0B7h ; 2 DB 09Fh ; 3 DB 04Fh ; 4 DB 0DDh ; 5 DB 0FDh ; 6 DB 08Bh ; 7 DB 0FFh ; 8 DB 0DFh ; 9 Start: MOV DH, 00h ; DH存十位(MSB),从0开始 MOV DL, 00h ; DL存个位(LSB),从0开始 Display: ; 显示个位(LSB):先选个位显示位,再输出段码 MOV AL, 00h OUT 02h, AL MOV AL, [DL] ; 取个位数字对应的段码 OUT 02h, AL ; 显示十位(MSB):选十位显示位,输出段码 MOV AL, 01h OUT 02h, AL MOV AL, [DH] ; 取十位数字对应的段码 OUT 02h, AL ; 判断是否到达终止条件:十位9,个位8 CMP DH, 09h JNZ NextNum CMP DL, 08h JZ Stop NextNum: ; 个位加2,超过8则重置为0,十位加1 ADD DL, 02h CMP DL, 0Ah JB Display MOV DL, 00h INC DH JMP Display Stop: HLT ; 终止程序 END
修改要点:
- 用
DH(十位)和DL(个位)分别计数,逻辑清晰匹配00到98的偶数序列。 - 按原代码选位逻辑(
00选个位、01选十位)依次输出段码。 - 直接判断
DH=9且DL=8作为终止条件,显示后立即停止。
3. 更优的MSB与LSB计数逻辑组织方式
可以采用单数值递增+拆分十进制位的方式,逻辑更简洁且扩展性更强:
JMP Start ; 段码表:数字0-9对应的7段码 DB 0FBh ; 0 DB 00Bh ; 1 DB 0B7h ; 2 DB 09Fh ; 3 DB 04Fh ; 4 DB 0DDh ; 5 DB 0FDh ; 6 DB 08Bh ; 7 DB 0FFh ; 8 DB 0DFh ; 9 Start: MOV AX, 00h ; AX存当前数值,从0开始 Display: PUSH AX ; 保存当前数值,避免DIV指令破坏 MOV BL, 10 DIV BL ; AL=十位,AH=个位 ; 显示个位 MOV AL, 00h OUT 02h, AL MOV AL, [AH] OUT 02h, AL ; 显示十位 MOV AL, 01h OUT 02h, AL MOV AL, [AL] ; AL为十位数字,直接取对应段码 OUT 02h, AL POP AX ; 恢复数值 ; 判断是否到达98 CMP AX, 98 JZ Stop ; 数值加2,继续循环 ADD AX, 02h JMP Display Stop: HLT END
这种方式的优势:
- 只用一个寄存器
AX维护数值,无需单独管理十位、个位计数器,逻辑紧凑。 - 拆分十进制位的逻辑通用,调整显示范围只需修改终止条件的数值,扩展性强。
- 减少了计数器维护的出错概率,避免出现越界或计数混乱问题。
内容的提问来源于stack exchange,提问作者Liheng Ouk
相关产品推荐
相关产品推荐

