8086系列(2):查找匹配字符串

题目

查找匹配字符串:

程序接收用户键入的一个关键字以及一个句子。如果句子中不包含关键字则显示’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.

在这里插入图片描述
调试结束,在程序正确的时候调试比较轻松,但在出错的情况下需要一步一步地观察,不断地尝试才能成功。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值