NASM 16位DOS COM程序:数组比较结果始终异常的问题排查
问题分析与修复:DOS .COM程序数组比较始终输出"Differ"
核心问题
1. 数组长度读取错误
你定义的n是字节类型(db 5),但用16位寄存器CX直接读取:mov cx, [n]。这会一次性读取n和紧随其后的1个字节(也就是array1第一个元素的低字节01),导致CX的值变成0105h而非预期的0005h。后续shr cx,1得到的循环次数完全错误,循环执行的次数远超过实际需要的2次,最终必然触发不相等的判断。
2. 循环与判断逻辑不匹配
原代码使用loopz指令,它的执行逻辑是:先将CX减1,再判断CX≠0且ZF=1(上一次比较相等)时才继续循环。循环结束后用jnz print_differ判断,但此时ZF的状态可能因为CX减到0而保留上一次比较的结果,逻辑容易混乱,导致错误跳转。
修复后的代码
use16 org 100h start: mov si, 2 ; array1奇数索引起始偏移(对应索引1) mov di, 0 ; array2偶数索引起始偏移(对应索引0) mov cl, [n] ; 读取字节长度到CL xor ch, ch ; 将CX扩展为16位,值为5 shr cx, 1 ; 计算需要比较的次数:5//2=2 jz print_match ; 无比较项直接输出匹配 comparison_loop: mov ax, [array1 + si] cmp ax, [array2 + di] jne print_differ ; 一旦发现不相等,直接跳转输出结果 add si, 4 ; 移动到下一个奇数索引(每个DW占2字节,索引+2对应偏移+4) add di, 4 ; 移动到下一个偶数索引 loop comparison_loop ; 循环直到CX为0 print_match: mov dx, msg_match jmp print print_differ: mov dx, msg_differ print: mov ah, 09h int 21h exit: mov ax, 4C00h int 21h n db 5 array1 dw 1, 2, 3, 4, 5 array2 dw 2, 0, 4, 0, 0 msg_match db 'Match.$' msg_differ db 'Differ.$'
修复说明
- 修正长度读取:用
mov cl, [n]读取字节长度,再用xor ch, ch将CX扩展为正确的16位值,确保循环次数准确。 - 简化判断逻辑:去掉
loopz,改用jne在发现不相等时直接终止流程,逻辑更直观;所有比较完成后自动进入print_match,避免了循环后复杂的标志位判断。 - 保持索引逻辑正确:原代码中
si和di的偏移计算是正确的(每个DW元素占2字节,奇数索引/偶数索引每次跳过一个元素,对应偏移+4),保留了这部分逻辑。
内容的提问来源于stack exchange,提问作者Muhab Joumaa
相关产品推荐
相关产品推荐

