汇编实验2.2 查找匹配字符串(附有详细注释和源代码和相关知识)
實驗2.2 查找匹配字符串
實驗要求:
程序接收用戶鍵入的一個關鍵字以及一個句子。如果句子中不包含關鍵字則顯示’No match!’;如果句子中包含關鍵字則顯示‘Match’,且把該字在句子中的位置用十六進制數顯示出來。
相關知識
1.為什么不能說直接 MOV DS,1000H 而是要通過AX設置首地址?
答:不可以,因為不允許將立即數直接傳送到段寄存器,這是mov命令本身的限制。
2.匯編語言中,CBW指令有何功能?
答:CBW 字節轉換為字指令執行的操作:AL的內容擴展到AH,形成AX中的字。
AL符號擴展為AX。在8086中CBW指令將AL的最高有效位D7擴展至AH,即:如果AL的最高有效位是0,則AH = 00,AL的最高有效位為1,則AH = FFH。AL不變。(即將AL的符號位移至AH)
CBW屬符號擴展指令,它可以把8位擴展到16位,擴展前后兩數的真值不變,主要用于數據類型不同時用符號擴展指令可以使得數據類型相同
3.匯編中的JS什么意思
JS(jump if sign),匯編語言中的條件轉移指令。結果為負則轉移
(https://zhidao.baidu.com/question/207589465.html 中有完整的各種轉移指令解釋)
4.匯編語言中的 offset什么意思
答:(1、OFFSET是將數值回送變量或標號的偏移地址值.
2.LEA是將數值回送變量或標號的有效地址值.
3.SEG, 匯編程序將回送變量或標號的段地址值.
4、LEA BX,LIST5、MOV BX,OFFSET LIST6、可以看出,LEA和OFFSET這兩條指令在功能上是相同的,BX寄存器都可得到符號地址LIST的值,而且此時MOV指令的執行速度會比LEA指令更快。但是,OFFSET只能與簡單的符號地址相連,而不能和諸如LIST[SI]或[SI]等復雜操作數相連。因此,LEA指令在取得訪問變量的工具方面是很有用的。)
5.SHL是邏輯左移,右邊的位補零,ROL是循環左移,左邊移出的位補到右邊
附帶注釋的源碼
(為方便,注釋用了//,其實用分號才對,最下面有沒有注釋的清潔的源代碼)
;··································································································
實驗2.2
;PROGRAM TITLE GOES HERE–search
;*******************************
datarea segment
mess1 db ‘Enter keyword:’,’′mess2db′EnterSentence:′,′' mess2 db 'Enter Sentence:','′mess2db′EnterSentence:′,′’
mess3 db ‘Match at location:’,’′mess4db′Nomatch!′,13,10,′' mess4 db 'No match!',13,10,'′mess4db′Nomatch!′,13,10,′ ’
mess5 db ‘match.’,13,10,’$ ’ //由于有match at,所以其實沒有用到mess5
mess6 db ‘H of the sentence.’,13,10,’$ ’
;
stoknin1 label byte //相當于定義了一個結構體
max1 db 10
act1 db ? //由于用戶還要輸入回車,所以最多能輸入的字符實際只有10-1=9個,
//返回給act1的是實際輸入的字符個數,它定義為字節類型的,所以以后
//通過mov想把act1的值賦值給cx時,就要cbw,把字節轉為字
stokn1 db 10 dup(?)
;
stoknin2 label byte
max2 db 50 //輸入字符串最多為49個字符,加上最后的回車
act2 db ?
stokn2 db 50 dup(?)
datarea ends
;*********************************
prognam segment
;---------------------------------
main proc far
assume cs:prognam ,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,mess1 ;提示:輸入關鍵字
mov ah,09
int 21h
lea dx,stoknin1 //mov ah,0ah的作用如下:
鍵盤輸入到緩沖區 DS:DX=緩沖區首地址
(DS:DX)=緩沖區最大字符數 (DS:DX+1)=實際輸入的字符數
a10: ;輸入句子
call crlf ;回車,換行
lea dx,mess2 //鍵盤輸入到緩沖區和顯示字符串,這兩個功能調用都是 以 DS:DX為地址的。
mov ah,09
int 21h
lea dx,stoknin2
mov ah,0ah //鍵盤輸入句子
int 21h
cmp act2,0
je nmatch //假如沒有輸入句子,那么也跳到nmatch上去
mov al,act1 //把關鍵字的長度賦值給al
cbw //cbw把字節轉為字
mov cx,ax
push cx //把關鍵字的長度賦值給cx
mov al,act2
sub al,act1
js nmatch //jump if sign,負則轉 若句子長度小于關鍵字長度,則轉到nmatch
mov di,0
mov si,0
lea bx,stokn2; //stokn2 是輸入的句子(的首地址),先把它放入bx中
inc al //將al+1,為什么?al中放句子的長度
a20:
mov ah,[bx+di] ;開始比較
cmp ah,stokn1[si] ;不等則轉到bx+1 //這里di加1可以嗎,不可以, //因為后面要用bx的內容減去句子的首地址,來得到匹配 //的位置,所以不匹配時bx+1,匹配時di+1
jne a30 ;bx+1
inc si
inc di //若當前相等,則把si和di都加1,繼續
dec cx //將要繼續比較的關鍵字長度減一,得到的新的cx的值是剩下的要 //比較的字符個數
cmp cx,0
je match //若沒比較完,繼續比較,否則關鍵字長度減為0后,匹配
jmp a20
a30: //若關鍵字的第一個字母和句子中的字母不相等,則跳轉到a30這兒 //來,也就是把句子中應該比較的字母的地址下標加1,將繼續 //要比較的句子中字母的個數(在al中)減一
inc bx
dec al
cmp al,0 //假如最后一個字母比較完都不匹配,那么跳轉到nmatch
je nmatch
mov si,0
mov di,0
pop cx //先pop,后push,是為這種情況設計的:句子:mnabde eabc 關鍵字:abc
//這時第一處ab其實是不匹配的,但是前面的a20中已經修改了cx的值,所//幸我們已經把cx=3的值在a10中push進入了堆棧,所以此時pop cx會將棧頂內容彈出并放入cx中,cx又變為了3,為了再次出現這種“只匹配前一部分,并不完全匹配”的情況,cx的內容能正確地恢復到關鍵字的長度,所以再次將cx push進去。
push cx
jmp a20 //?為什么又跳轉到開始比較的地方呢 答:當前不匹配,不代表一直不匹配,只要句子未結束,就要一直比較下去
exit:
call crlf
ret
nmatch: ;no match則輸出No match
call crlf
lea dx,mess4
mov ah,09
int 21h
jmp a10 //再次輸入一個句子
match: ;match則輸出位置信息
call crlf
lea dx,mess3 //mess3 db ‘Match at location:’,’$’
crlf proc near ;回車,換行
mov dl,0dh ;?不用先push dx嗎?是的,若返回回去的上下文中沒有用到dx,那也可以 不push呀
mov ah,2
int 21h
mov dl,0ah
mov ah,2
int 21h
ret
crlf endp
trans proc near ;轉換為16進制,參考書上例6.3,執行trans時,bx中存放的 //是已經得到的匹配位置的二進制表示
mov ch,4 ;number of digits
rotate:
mov cl,4 ;set count to 4bits
rol bx,cl ;left digit to right //rol循環左移,把bx循環左移4位
mov al,bl ;mov to al
and al,0fh ;mask off left digit //取低四位,也就是前面二進制串中的高四位
add al,30h ;convert hex to ASCII
cmp al,3ah ;is it>9? 數字9的ASCii碼為57d,也就是39h,3ah是9的下一個 //字符
jl printit ;jump if digit=0 to 9 //jump if less
add al,7h ;digit is A to F //是字母的話,就順序執行printit,也會打印,是數字
//不用加7了,直接跳轉到打印處
printit:
mov dl,al ;put ASCII char in DL
mov ah,2 ;Display Output funct //ah=02 顯示輸出DL=輸出字符
int 21h ;call DOS
dec ch ;done 4 digits? //將ch-1,ch控制轉換次數,最終要得到4個16 //進制數字
jnz rotate ;not yet
ret ;return from trans
trans endp ;
main endp
;----------------------------------
prognam ends
;**********************************
end start
源碼:
;PROGRAM TITLE GOES HERE–search
;*******************************
datarea segment
mess1 db ‘Enter keyword:’,’′mess2db′EnterSentence:′,′' mess2 db 'Enter Sentence:','′mess2db′EnterSentence:′,′’
mess3 db ‘Match at location:’,’′mess4db′Nomatch!′,13,10,′' mess4 db 'No match!',13,10,'′mess4db′Nomatch!′,13,10,′ ’
mess5 db ‘match.’,13,10,’$ ’
mess6 db ‘H of the sentence.’,13,10,’$ ’
;
stoknin1 label byte
max1 db 10
act1 db ?
stokn1 db 10 dup(?)
;
stoknin2 label byte
max2 db 50
act2 db ?
stokn2 db 50 dup(?)
datarea ends
;*********************************
prognam segment
;---------------------------------
main proc far
assume cs:prognam ,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,mess1 ;輸入關鍵字
mov ah,09
int 21h
lea dx,stoknin1
mov ah,0ah
int 21h
cmp act1,0
je exit
a10: ;輸入句子
call crlf
lea dx,mess2
mov ah,09
int 21h
lea dx,stoknin2
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,stokn2;
inc al
a20:
mov ah,[bx+di] ;開始比較
cmp ah,stokn1[si] ;不等則轉到bx+1
jne a30 ;bx+1
inc si
inc di
;inc bx
dec cx
cmp cx,0
je match
jmp a20
a30:
inc bx
dec al
cmp al,0
je nmatch
mov si,0
mov di,0
pop cx
push cx
jmp a20
exit:
call crlf
ret
nmatch: ;no match則輸出No match
call crlf
lea dx,mess4
mov ah,09
int 21h
jmp a10
match: ;match則輸出位置信息
call crlf
lea dx,mess3
mov ah,09
int 21h
sub bx,offset stokn2
inc bx
call trans
lea dx,mess6
mov ah,09
int 21h
jmp a10
crlf proc near ;回車,換行
mov dl,0dh
mov ah,2
int 21h
mov dl,0ah
mov ah,2
int 21h
ret
crlf endp
trans proc near ;轉換為16進制,參考書上例6.3
mov ch,4 ;number of digits
rotate: mov cl,4 ;set count to 4bits
rol bx,cl ;left digit to right
mov al,bl ;mov to al
and al,0fh ;mask off left digit
add al,30h ;convert hex to ASCII
cmp al,3ah ;is it>9?
jl printit ;jump if digit=0 to 9
add al,7h ;digit is A to F
printit:
mov dl,al ;put ASCII char in DL
mov ah,2 ;Display Output funct
int 21h ;call DOS
dec ch ;done 4 digits?
jnz rotate ;not yet
ret ;return from trans
trans endp ;
main endp
;----------------------------------
prognam ends
;**********************************
end start
————————————————
運行結果:
總結
以上是生活随笔為你收集整理的汇编实验2.2 查找匹配字符串(附有详细注释和源代码和相关知识)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: movsb movsw movsd 指令
- 下一篇: 汇编实验 用表格形式显示字符(附源码详细