;朴素的字符长匹配
;默认为200个字符长度,超过长度将自动截断
assume cs:codes
;被匹配的字符串
string segment
db 'lsadkniueynbkdbbdkhgvakljerufdkknnegbaidhfkldkngn.xz/rmwe4984'
string ends
;要匹配的字符串
substring segment
db 'dk'
substring ends
;两个字符串的各自长度上限和实际长度StringMaxsize ,StringLength , subStrMaxsize , subStrLength
lengths segment
dw 200,61,200,2
lengths ends
;记录每个匹配出的字符串的在string中的位置,只记录匹配substring最后一个字母时的索引
position segment
dw 200 dup(0)
position ends
buffer segment
db 16 dup(0)
buffer ends
codes segment
str3:
db ">>Total Num:",'$'
str4:
db ">>Matched String Result:",'$'
start:
mov ax,0500h ;直接写显存(b800h)显示字符时, 在windows 2003 server系统的
int 10h ;控制台直接直接执行可执行文件, 无法显示.置0页为显示页.
mov ah , 02 ;置光标位置
mov dx , 0100H
mov bh , 0
int 10H
call cls
mov bx , cs
mov ds , bx
mov dx , offset str3
call printStr
mov bx , lengths
mov ds , bx
mov cx , ds:[2]
mov bx , string
mov ds , bx
call match
;显示匹配出的子字符串的个数
push cx
mov ax , cx
mov dx , 0
call divsub ;数据分解成数字
mov ax , buffer
mov ds , ax
mov cx , si
num:mov dl , ds:[si-1]
add dl , 30H
call printChar
sub si , 1
loop num
call CRandLF
pop cx
cmp cx , 0H
je over
mov bx , cs
mov ds , bx
mov dx , offset str4
call printStr
call CRandLF
call matchResultList ;匹配后的显示
over:
mov ah , 07H
int 21H
MOV AH,4CH
INT 21H
;==============================
;输出字符串,给定字符串的首地址ds:dx
printStr:
push ax
mov ah , 09H
int 21h
pop ax
ret
;==============================
;显示一个字符,默认参数放dl
printChar:
push ax
mov ah , 02H
int 21h
pop ax
ret
;==============================
;回车,换行
CRandLF:
push dx
push ax
mov dl , 0DH
mov ah , 02H
int 21h
mov dl , 0AH
mov ah , 02
int 21h
pop ax
pop dx
ret
;=============================================
;将输入的字符放到相应的内存中保存
;ds内存段地址,dx内存的maxsize ,cx 内存的length ,al 字符内容
save:
push bx
cmp cx , dx
jnb saveRet ;length 不小于 maxsize 的时候,空间满,字符不再添加
mov bx , cx
mov byte ptr ds:[bx] , al
add cx , 1
saveRet:
pop bx
ret
;===================================
;匹配 ax保存返回值 ax=0 没有匹配字符串; ax = 1 string 或 substr 为空
;cx 有多少个匹配成功的子串
match:
push ds
push ax
push bx
push dx
push si
push di
mov cx , 0H
mov bx , lengths
mov ds , bx
mov si , ds:[2] ;string's length
mov di , ds:[6] ;substring's length
cmp si , 0H ;被匹配和要匹配的字符串是否为空
je emptyErro
cmp di , 0H
je emptyErro
cmp di , si ; substring's length > string's length ,不可能匹配
ja matchErro
mov dx , 0H ;记录string比较到那个位置了
A:mov si , dx ;从记录位置开始匹配
mov di , 0 ;记录substring比较到那个位置了
B:mov bx , lengths
mov ds , bx
cmp di , ds:[6] ;substring遍历到头了,说明找出一个匹配的字符串了
jnb matchOne
cmp si , ds:[2] ;string遍历到头了,匹配结束
jnb matchRet
mov bx , string
mov ds , bx
mov al , ds:[si]
mov bx , substring
mov ds , bx
cmp al , ds:[di]
jne next
add si , 1
add di , 1
jmp B
matchOne:
mov bx , position ;每匹配出一处substring就记录最后一个字母的索引
mov ds , bx
mov bx , cx
push ax
push dx
mov ax , 02H
mul bx
mov bx , ax
pop dx
pop ax
mov word ptr ds:[bx] , si
add cx , 1 ;匹配出一个就将计数加一
next:add dx , 1
jmp A
matchErro:
mov ax , 0H
jmp matchRet
emptyErro:
mov ax , 1H
matchRet:
pop di
pop si
pop dx
pop bx
pop ax
pop ds
ret
;============================================================
;将匹配完成的string打印出来,并标识出匹配出来的各个字符段。
;输入参数cx表示匹配串的个数
matchResultList:
push ds
push ax
push bx
push dx
push di
push si
mov bx , 0B800H
mov es , bx
mov bp , 480 ;显示位置
mov bx , string
mov ds , bx
mov bx , 0 ;string 的游标
resStart:
mov si , 0
cmp cx , 0
je next2
push cx
S:mov ax , position
mov ds , ax
mov ax , ds:[si] ;取得的数值=索引+1
push ax
mov ax , lengths
mov ds , ax
pop ax
mov di , ax
sub ax , ds:[6] ;是不是左'['
cmp bx , ax
jne Right
mov dl , '<'
mov byte ptr es:[bp] , dl
mov byte ptr es:[bp+1] , 0AH
add bp , 2
Right:
mov ax , di
cmp bx , ax
jne nextOne
mov dl , '>' ;是不是右']'
mov byte ptr es:[bp] , dl
mov byte ptr es:[bp+1] , 0AH
add bp , 2
nextOne:
add si , 2
loop S
pop cx
next2:
mov ax , lengths
mov ds , ax
cmp bx , ds:[2]
jnb resultRet
mov ax , string
mov ds , ax
mov dl , ds:[bx]
mov byte ptr es:[bp] , dl
;mov byte ptr es:[bp+1] , 0AH
add bp , 2
add bx , 1
jmp resStart
resultRet:
pop si
pop di
pop dx
pop bx
pop ax
pop ds
ret
;================================================
;将一个多位数转化成一个个数字,同时解决不溢出的除法
;ax数据低16位,dx数据高16位,si记录分析出来的字符的个数
divsub:
push ds
push bx
push cx
push dx
push di
mov di , 0AH ;除数为10
mov bx , buffer
mov ds , bx
mov si , 0 ;si为记录数据个数的,用来向缓冲去输入数据是寻址
go:
cmp dx , 0H
je gonext
goon:
push ax
mov ax , dx
mov dx , 0
div di ;商在ax,余数在dx
mov cx , ax ;把商先保存
pop ax
div di
mov byte ptr ds:[si] , dl ;余数放到数据缓冲区
add si , 1
mov dx , cx
jmp go
gonext:
cmp ax , 0H
jne goon
cmp si , 0H
jne divRet
mov byte ptr ds:[si] , 0H
add si , 1
divRet:
pop di
pop dx
pop cx
pop bx
pop ds
ret
;==============================================
;清屏 ,并显示版权信息
cls:
push es
push bx
push cx
push si
mov bx , 0B800H
mov es , bx
mov bx , 0
mov cx , 25
CA:push cx
mov si , 0
mov cx , 80
CB:mov byte ptr es:[bx+si] , 20H
add si , 2
loop CB
add bx , 160
pop cx
loop CA
pop si
pop cx
pop bx
pop es
ret
codes ends
end start
[07/10/12] |