8086汇编CMPSB指令单词匹配异常问题求助
问题分析与解决方案
核心问题
你的代码存在两个致命逻辑错误,导致部分单词匹配失败:
- 字典无单词边界:
str1中的单词是连续存储的(如"foe""grim"实际是f o e g r i m...),没有分隔符(比如空字节0x00),repne cmpsb无法区分独立单词,会跨单词进行无效比较。 - 错误的比较范围:直接将
CX设为字典总长度18,repne cmpsb会从起始位置一直比较到CX耗尽,而非针对单个单词进行匹配。当目标单词不在字典起始位置时,前面不匹配的字节会持续消耗CX,直到目标单词位置时剩余CX可能不足以完成完整匹配,或者后续不匹配的字节直接耗尽CX。
解决方案
1. 给字典添加单词分隔符
在每个单词末尾添加空字节0x00,明确单词边界:
str1: db "foe",0,"grim",0,"toll",0,"true",0,"fur",0 find: db "grim",0 ; 目标单词也添加结束符,统一判断逻辑
2. 重写匹配逻辑
改为遍历字典中的每个单词,逐个与目标单词比较。具体步骤:
- 遍历字典,每次定位到一个单词的起始地址
- 逐字节比较当前字典单词与目标单词,同时检查是否到达单词结束符
- 若完全匹配则返回成功,否则继续遍历下一个单词
修改后的完整代码
[org 0x0100] jmp start ; 字典:每个单词后加0x00作为分隔符 str1: db "foe",0,"grim",0,"toll",0,"true",0,"fur",0 ; 目标单词:同样加结束符 find: db "grim",0 ; 比较单个单词的子函数 ; 参数:[bp+4] = 字典单词地址, [bp+8] = 目标单词地址 ; 返回:ZF=1表示匹配成功,ZF=0表示失败 cmp_word: push bp mov bp, sp push si push di mov si, [bp+4] ; 字典单词地址 mov di, [bp+8] ; 目标单词地址 compare_loop: mov al, [si] mov bl, [di] cmp al, bl jne match_fail ; 字节不匹配,失败 cmp al, 0 ; 到达结束符,说明完全匹配 je match_success inc si inc di jmp compare_loop match_success: pop di pop si pop bp ret 4 ; 清理参数栈,同时保持ZF=1 match_fail: pop di pop si pop bp ret 4 ; 清理参数栈,同时保持ZF=0 ; 主匹配函数:遍历字典所有单词 comp: push bp mov bp, sp pusha mov si, [bp+4] ; 字典起始地址 mov bx, [bp+8] ; 目标单词地址 dict_loop: cmp byte [si], 0 je match_end ; 遍历到字典末尾,无匹配 push si push bx call cmp_word ; 比较当前单词 jz match_found ; ZF=1,匹配成功 next_word: ; 移动到下一个单词(跳过当前单词直到0x00) inc si cmp byte [si], 0 jne next_word inc si ; 跳过0x00,到下一个单词起始 jmp dict_loop match_found: ; 这里可以添加匹配成功后的处理逻辑,比如设置标志位 mov ax, 1 ; 用ax=1表示匹配成功 jmp comp_end match_end: mov ax, 0 ; ax=0表示匹配失败 comp_end: popa pop bp ret 4 ; 清理参数栈 start: push ds push str1 push ds push find call comp ; ax=1表示匹配成功,ax=0表示失败,可根据需求处理 mov ax, 0x4c00 int 21h
代码说明
cmp_word子函数负责逐字节比较单个单词,同时检查结束符,确保只有完整单词匹配才返回成功。comp函数遍历字典中的每个单词,调用cmp_word进行匹配,直到找到匹配项或遍历完所有单词。- 调试时可通过观察
AX寄存器的值判断匹配结果(1为成功,0为失败),也可添加其他标志位或输出逻辑。
内容的提问来源于stack exchange,提问作者hadi khan
相关产品推荐
相关产品推荐

