题目
查找匹配字符串:
程序接收用户键入的一个关键字以及一个句子。如果句子中不包含关键字则显示’No match!’;如果句子中包含关键字则显示‘Match’,且把该字在句子中的位置用十六进制数显示出来。
思路
(1) 输入关键字和一个句子,分别存入相应的缓冲区
(2)在句子中查找关键字
关键字和句子中相应字段的比较可以使用串比较指令,附加段和数据段定义为同一段,以便串指令的使用。
下面说明比较过程中寄存器的使用情况:
SI:存放原串首地址
DI:存放目的串首地址
CL:关键字长度 (keyword的长度)
AX:目的串(sentence)的偏移量
每调用一次串比较指令,都有3个分支,
一是匹配成功,转入match
二是未匹配但还未越界,则继续比较 ax+1
三是已经越界,转入No match
流程图如下:
代码
datasg segment
mess1 db 'Enter keyword:','$'
mess2 db 'Enter Sentence:','$'
mess3 db 'Match at location:','$'
mess4 db 'No match.',13,10,'$'
mess5 db 'H of the sentence',13,10,'$'
mess6 db 13,10,'$'
keyword label byte
max1 db 20
act1 db ?
kw db 20 dup(?)
sentence label byte
max2 db 120
act2 db ?
sen db 120 dup(?)
datasg ends
codesg segment
assume cs:codesg,ds:datasg,es:datasg
main proc far
start:
push ds
xor ax,ax
push ax
mov ax,datasg
mov ds,ax
mov es,ax
;;;;;;开始自定义代码
lea dx,mess1
mov ah,09
int 21h ;调用09号中断输出mess1
lea dx,keyword
mov ah,0ah
int 21h ;调用0a号中断进行keyword的输入
lea dx,mess6 ;换行/回车
mov ah,09
int 21h
recome:
lea dx,mess2 ;调用09号中断输出mess1
mov ah,09
int 21h
lea dx,sentence ;调用0a号中断进行sentence的输入
mov ah,0ah
int 21h
lea dx,mess6 ;换行/回车
mov ah,09h
int 21h
mov ax,0
loop1:
sub cx,cx ;;;;
mov cl,act1 ;关键字长度赋值cl
lea si,kw ;原串首地址kw
lea bx,sen
add bl,al
mov di,bx ;目的串首地址(不断变化,ax记录目的串偏移量)
cld ;df=0 正向比较
repe cmpsb ;
jz match ;相等zf=1,match
;
inc al ;ax记录串偏移量
cmp al,act2 ;判断是否越界,注意要对齐(调试了半天,写成ax就不行)
jnb loop2 ;no match
jmp loop1 ;还没比较完成
match:
mov bx,0
mov bl,al
add bx,1 ;需要从1开始计数
lea dx,mess3
mov ah,09
int 21h
;;;输出bx中的十六进制数
mov cl,4
rol bx,cl
rol bx,cl
mov ch,2 ;ch用于循环移位
rotate: ;这里使用到了循环
mov cl,4 ;cl用于每次移4位,rol的操作数不能是立即数
rol bx,cl ;循环右移4位
mov ax,bx
and al,0fh ;取低四位
add al,30H ;’0’-’9’ ASCII 30H-39H 转化为
cmp al,3aH ;比3a小的是数字,则直接跳转输出
jb printf ;这里使用到了分支
add al,07h ;否则再加上07h ’A’-’F’ ASCII 41H-46H
printf:
mov dl,al
mov ah,2 ;调用2号中断输出字符串
int 21h
dec ch ;ch-1
jnz rotate ;如果ch不等于0,继续循环
;;;;
lea dx,mess5
mov ah,09
int 21h
lea dx,mess6
mov ah,09
int 21h
jmp recome
loop2:
lea dx,mess4 ;;输出NO match
mov ah,09
int 21h
jmp recome
exit:
ret
main endp
codesg ends
end start
调试过程
反汇编
要不就go到003B吧,并观察数据的存放结构
那就一路t下去吧,观察寄存器的变化情况
我们可以事先得知,在ax=16的时候才会进入match分支,我们可以修改寄存器ax的值,加速循环
一路t下去,一直到了该跳转的地方了,发现确实跳去了match
由于上个程序我已经调试好了将bx的值以16进制输出,我们就直接查看结果吧,发现匹配的部分没有毛病。
下面继续调试No match的部分,还是go到003B来观察它的数据部分,发现覆盖了原来的sentence字段,但是输入时有保存sentence的长度,并无大碍。
按照上述的方法修改寄存器ax的值为0007,(因为预计在8的位置跳转)继续调试,观察是否跳转。
可以跳去No match部分了,程序应该没什么问题了,直接go到底,输出No match.
调试结束,在程序正确的时候调试比较轻松,但在出错的情况下需要一步一步地观察,不断地尝试才能成功。