8086汇编列表唯一值提取宏未生效,输出与原列表一致问题排查
8086去重汇编程序故障排查与修复方案
核心故障定位
- 输出逻辑存在硬错误:主程序中
mov dx,offset di是非法写法。offset操作符仅能获取内存标号的段内偏移,无法应用在寄存器DI上。这行代码实际运行时无法正确加载目标字符串list2的起始地址,会导致DOS中断输出时访问到原列表list1的地址区间,最终输出内容和原列表完全一致。 - 目标列表存储存在空隙:在存储最后一个有效元素后,
inc di会移动到下一个位置,之后判断到SI指向字符串结束符$时,会先执行一次inc di再存入结束符,导致目标列表中在最后一个有效元素和结束符之间出现1个未初始化的随机字节,输出时会出现乱码。 - 标志位逻辑存在冗余路径:当前
CX标志仅用来标记“是否碰到过匹配项”,虽然能正确区分自身位置匹配和重复匹配,但在触发第二次匹配时直接跳转,没有终止BX的遍历流程,会无意义延长扫描路径。
修复后代码
修正后的宏实现
调整结束符存储位置消除空隙,移除无效寄存器操作:
uniqueElement macro list1 list2 local loop1,comparasionLabel,checkFlag,trigger,nextElement,addElement,endAddition lea si,list1 lea di,list2 loop1: mov cx,00H ; 初始化重复标志:0=未碰到过匹配 lea bx,list1 ; 从列表起始位置开始扫描 mov al,BYTE PTR[SI] cmp al,'$' ; 碰到结束符则退出循环 je endAddition comparasionLabel: mov dl,BYTE PTR[BX] cmp dl,'$' ; 扫描到列表结尾,说明没有第二次匹配,保留当前元素 je addElement cmp al,dl je checkFlag inc bx jmp comparasionLabel checkFlag: ; 第一次碰到匹配:置标志位,继续扫描后续元素,看是否存在第二次匹配 cmp cx,00H je trigger ; 已经是第二次碰到匹配:当前元素重复,跳过 cmp cx,01H je nextElement trigger: mov cx,01H inc bx jmp comparasionLabel nextElement: inc si jmp loop1 addElement: mov BYTE PTR [di],al inc di inc si jmp loop1 endAddition: ; 直接在当前di位置存入结束符,消除存储空隙 mov al,'$' mov BYTE PTR[di],al endm
修正后的主程序
替换错误的输出地址加载逻辑:
.model small .data list1 db 'H3llo$' list2 db 50 DUP [?] .code mov ax,@data mov ds,ax uniqueElement list1 list2 ; 加载目标列表的起始偏移用于输出 mov ah,09H mov dx,offset list2 int 21h .exit
修复后效果
针对示例输入H3llo$(包含两个重复的小写l),程序会输出去重后的字符串H3lo$,完全符合唯一元素留存的预期。
内容的提问来源于stack exchange,提问作者HuangLinBao
相关产品推荐
相关产品推荐

