彙編實驗:自定義鍵盤中斷的處理函式
阿新 • • 發佈:2022-11-29
彙編實驗報告-鍵盤中斷
1. 實驗任務:採用鍵盤中斷方式,當輸入是字元或數字的時候,回顯輸入並回車換行;否則退出。
2. 執行環境:Windows11+MASM
3. 題目分析:
在課上我們剛剛學習了中斷的概念以及自定義中斷,且有一個例程是對鍵盤中斷進行獲取的。因此我們可以借鑑例程,通過mov ah 25h/35h完成對鍵盤中斷的存取和設定,獲取鍵入的字元。
但是最開始想直接輸出獲取的字元卻發現均為亂碼,查詢後才發現由鍵盤中斷方式讀取的是字元的掃描碼,該碼與ASCII碼不同,是鍵盤上第一排“0-9,-=”有鄰近的掃描碼,第二排“qwertyuiop[]|”有鄰近的掃描碼等等。於是我們找到掃描碼和字元的對應表,手動建立一個字串,儲存從00H-39H的所有字元,如果不是可顯示字元,或是控制字元,就用#代替。通過這種方式可以把掃描碼直接對映到對應字元的ASCII碼輸出。
4. 流程圖繪製:根據分析和題目要求繪製主函式的流程圖:
5. 各部分與功能的流程圖/程式:
- 資料段定義:當我們定義資料段時,我們要考慮的有以下幾方面因素:
-
由於設定中斷前必須儲存原有中斷處理函式,結束後必須恢復原中斷,因此需要2個儲存區分別儲存原有中斷的段地址和偏移地址。
-
由於需要把掃描碼轉換為ASCII碼輸出,我們需要定義一個字串,其與串首址的偏移距離即為掃描碼,其值即為ASCII碼。
資料段定義:
data segment old_ip09 dw ? old_cs09 dw ? endmsg db 0ah,0dh,'END',0ah,0dh,'$' scan db "##1234567890-=##qwertyuiop[]##asdfghjkl;'###zxcvbnm,./",'$' data ends codesg segment
- 中斷處理函式kbdit:
該函式就是當我們觸發鍵盤中斷時,會呼叫的處理程式。其功能為首先從鍵盤緩衝區埠60H接受掃描碼,然後與資料段中我們定義的字串偏移量匹配,如果是#則放棄輸出,否則判斷為正確字元、輸出該字元。
- 流程圖
- 程式段程式碼如下:
kbdit PROC push dx push ax push bx in al,60h push ax in al,61h mov ah,al or al,80h out 61h,al xchg ah,al out 61h,al pop ax in al,60h test al,80h;若超過127,退出 jnz return lea bx,scan DISPLAY: ;CBW ; mov cx,ax ; GO: sub ah,ah ADD bx,ax mov dl,[bx] cmp dl,'#';不合格 je exit mov ah,02H int 21h return: cli mov al,20h out 20h,al pop bx pop dx pop ax iret kbdit ENDP
-
主函式main
主函式的作用是設定中斷向量,並且進行延時,等待中斷程式的呼叫。
-
流程圖
-
程式段程式碼如下:
main proc near
start:
push ds
sub ax,ax
push ax
mov ax,data
mov ds,ax
mov es,ax
;save old inter
mov al,09h
mov ah,35h;取中斷向量
int 21h
mov old_cs09,es;儲存原有中斷
mov old_ip09,bx
push ds
lea dx,kbdit
mov ax,seg kbdit
mov ds,ax
mov al,09h
mov ah,25h;中斷向量設定
int 21h
pop ds
;開啟鍵盤中斷遮蔽
in al,21h
and al,0fdh;00001111
out 21h,al
sti
;開始準備服務中斷
mov di,20000
wait1:
mov si,3000
wait2:
dec si
jnz wait2
dec di
jnz wait1
mov ah,09h
lea dx,endmsg
int 21h
cli
;恢復原先的中斷
push ds
mov dx,old_ip09
mov ax,old_cs09
mov ds,ax
mov al,09h
mov ah,25h
INT 21h
pop ds
ret
;結束
exit:
lea dx,endmsg
mov ah,09h
int 21h
mov ah,4ch
int 21h
main ENDP
6.執行結果
-
0-9數字排的輸出
-
三個字母排的輸出
可見功能正常,成功實現。
- 現存問題:由於我們認為SHIFT是不合法的字元,因此我們無法實現SHIFT+小寫字母輸出大寫字母的功能。