汇编实现字符串匹配计数以及变色显示
题目描述:
输入想要搜索的字符集,在字符串中寻找字符集的出现次数,
以及变色(或闪烁)显示字符串中的字符集。
整个实验过程中出现的问题:
因为没有使用CX来进行双层循环,只是利用CX判断串是否相等,而利用AL寄存器来控制外层循环,所以在记录AL的值的时候,记录的是位置加上一个串的长度减一的值,并且在不断的压栈的过程中,最后出栈上色时扫描是从前往后扫描,但是出栈的位置是从后往前,如何解决这个问题?选择利用多次扫描,每一扫描值对一个栈中的位置进行上色,为了提高效率,一旦找到目标位置进行上色后,开始下一轮的查找。
在查找串的过程中,可以通过判断目标串和查找串的长度大小就可以判定是否有匹配的串存在,如果查找串本身就比目标串小,那么显然不可能有目标串存在有查找串中。
另外遇到的一个问题是,最开始设计的时候使用的查找方法是,如果出现了串中开头字符相同的状况,就将长串和短串字符循环大小都减一,指针向后移动,一旦出现不匹配的现象,只将长串的指针向后移动,但是最后在测试的过程中明显的出现了一个问题,就是在不匹配处,恰好出现的是一个新的目标串的情况,所以对代码进行改进,出现不匹配时,短串字符指针复位,长串指针不动,依旧从不匹配出重新开始扫描。
存储串的结构:
datarea segment
message1 db 'Enter keyword:','$'
message2 db 'Enter Sentence:','$'
message3 db 'Match at location:','$'
message4 db 'No match!',13,10,'$ '
message5 db 'match.',13,10,'$ '
message6 db 'H of the sentence.',13,10,'$ '
;
s1 label byte
max1 db 10
act1 db ?
str1 db 10 dup(?)
;
s2 label byte
max2 db 50
act2 db ?
str2 db 100 dup(?)
datarea ends
;*********************************
解决方法和实验代码
方法一:
因为可以直接在字符和存储的区域内找到记录的字符串的大小,所以在查找
字符串的过程中,当找到目标串时,先将当前CX的值减去小串的长度在入栈(记录位置),
再将CX原来的值入栈,同时记录目标串出现的次数加一,跳转到循环将CX的
设置为小串的大小,回退一个目标字符串的大小开始上色,上完色后出栈继续循环。
方法二:(将各个模块的功能拆分)
在查找目标字符串时,当发现找到目标串时,将记录长串位置的值入栈,
同时将次数加一,一次循环之后开始上色,先扫描一遍将字符串上色为黑色,再一次扫描,
当扫描的位置与目标位置相同时,跳转变色。
第二种方案的实现:
;============得到字符串和字符集的输入(长度和本身字符串信息也一起记录)
program segment
;---------------------------------
main proc far
assume cs:program ,ds:datarea,es:datarea
start:
push ds
sub ax,ax
sub bx,bx
push ax
mov ax,datarea
mov ds,ax
mov es,ax
;MAIN PART-------------
lea dx,message1 ;在屏幕上显示提示输入字符串
mov ah,09
int 21h
lea dx,s1 ;得到字符串的输入
mov ah,0ah
int 21h
cmp act1,0
je exit ;当未输入时提示
a10: ;输入句子
call crlf
lea dx,message2
mov ah,09
int 21h
lea dx,s2
mov ah,0ah
int 21h
cmp act2,0
je nmatch ;没有输入直接跳转到没有匹配
mov al,act1
cbw ;符号扩展指令
mov cx,ax
push cx
mov al,act2
sub al,act1 ;句子比单词小就说明没有匹配的
js nmatch
mov di,0
mov si,0
lea bx,str2;
mov al,act2;字符串的长度
mov di,0
;=================记录次数和字符集出现的位置
a20:
mov ah,[bx] ;开始比较
cmp ah,str1[si] ;不等则转到bx+1
jne a30 ;bx+1
inc si
inc bx
;inc di
dec cx
cmp cx,0
je count
a50:
dec al;字符串的长度--
;同时判断字符串的长度是否已经为0
;如果还有则重新进入判断比较
cmp al,0
je a40
jmp a20
a60:
mov si,0
pop cx
push cx
jmp a20
a30:
cmp ah,str[0]
je a60
inc bx
dec al
cmp al,0
je nch
mov si,0
;mov di,0
pop cx
push cx
jmp a20
exit:
call crlf
ret
count:
inc di ;可以进行标记和添加颜色
pop cx ;单词的长度
push ax
push cx
mov si,0
jmp a50
a40:
cmp al,0
je match
jmp a20
nch:
cmp di,0
je nmatch
jmp match
nmatch: ;no match则输出No match
call crlf
lea dx,message4
mov ah,09
int 21h
jmp a10
match:
call crlf
mov dx,di
push dx
add dx,30h
mov ah,02h
int 21h
;match则输出位置信息
call crlf
;=======================输出对应位置变色的字符串
pop cx
pop cx;要显示的字符的数量
;======================================
mov al,act2
cbw
mov cx,ax
;add di,di
;dec si
mov ax,0b872h
mov es,ax
push di
mov si,0
mov di,0
lea bx,str2
;push cx;str2
;mov cx,di;出现次数
c1:
mov al,[bx+si]
mov es:[di],al
mov al,70h
mov es:[di+1],al
inc si
add di,2
loop c1
pop di
mov cx,di
;push cx
;mov dx,cx
;add dx,30h
;mov ah,02h
;int 21h
s0:
push cx
mov si,0
mov di,0
s1:
;call crlf
pop cx
;mov dx,cx
;add dx,30h
;mov ah,02h
;int 21h
pop dx;位置有问题
push dx
;push cx
;
;add dx,30h
;mov dx,si
;mov ah,02h
;int 21h
;inc si
;判断是否和目标位置相等相等的话就上色
mov al,act2
sub al,dl
inc al
sub al,act1
cbw
cmp ax,si
je p1
inc si
add di,2
push cx
mov al,act2
cbw
cmp ax,si
je s4
mov cx,2
loop s1
s4:
pop cx
loop s0
jmp p3
p1: pop dx
;add dx,30h
;mov ah,02h
;int 21h
jmp str1
p2:
mov al,[bx+si]
mov es:[di],al
mov al,79h
mov es:[di+1],al
;dec si
inc si
add di,2
;sub di,2
loop p2
;pop cx
;mov al,act2
;dec al
;cbw
;cmp ax,si
;push cx
jmp s4
;mov cx,si;避免下一轮的循环
;jmp s1;进行新的一轮循环
str1:
mov al,act1
cbw
;sub cx,ax
push cx
mov cx,ax
jmp p2
p3: mov ah,4ch
int 21h
crlf proc near ;回车,换行
mov dl,0dh
mov ah,2
int 21h
mov dl,0ah
mov ah,2
int 21h
ret
crlf endp
;
main endp
;----------------------------------
prognam ends
;**********************************
end