汇编实现字符串匹配计数以及变色显示

汇编实现字符串匹配计数以及变色显示

题目描述:

	输入想要搜索的字符集,在字符串中寻找字符集的出现次数,
	以及变色(或闪烁)显示字符串中的字符集。

整个实验过程中出现的问题:

因为没有使用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

实验结果

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
汇编语言中可以使用循环和 ASCII 码来查找字符串中的数字。 首先,我们需要定义一个字符串指针,指向要查找数字的字符串。 然后,使用循环遍历字符串中的每个字符。在每个字符上,我们可以使用 ASCII 码来检查它是否是数字。数字字符的 ASCII 码在 0x30 到 0x39 之间。如果字符是数字,我们可以将其存储在一个缓冲区中,以便稍后处理。 最后,我们可以将缓冲区中的数字转换为十进制数,并将其存储在寄存器中或存储在内存中的某个位置中。 下面是一个示例程序,演示了如何在字符串中查找数字: ``` section .data str db 'abc123def', 0 buf db 10 dup(0) section .text global _start _start: ; 初始化字符串指针 mov esi, str ; 初始化缓冲区指针 mov edi, buf ; 循环遍历字符串中的每个字符 jmp start_loop loop_char: ; 检查字符是否是数字 cmp byte [esi], 0x30 jb end_loop cmp byte [esi], 0x39 ja end_loop ; 如果字符是数字,将其存储在缓冲区中 mov byte [edi], byte [esi] inc edi end_loop: ; 移动字符串指针到下一个字符 inc esi start_loop: ; 如果字符串未结束,继续循环 cmp byte [esi], 0 jne loop_char ; 输出结果 mov eax, 4 mov ebx, 1 mov ecx, buf sub edi, buf mov edx, edi int 0x80 ; 退出程序 mov eax, 1 xor ebx, ebx int 0x80 ``` 在本示例中,我们在字符串中查找数字,并将其存储在缓冲区中。然后,我们使用 Linux 系统调用 `write` 输出缓冲区中的数字。最后,我们使用系统调用 `exit` 退出程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值