汇编语言随笔(15)- 对键盘输入进行处理(int 9 和 int 16h 中断例程)
鍵盤輸入
??????1,前面講過, int 9 中斷例程負責對鍵盤輸入進行處理,具體為:從 60h 端口讀出掃描碼,并將其轉化為相應的ASCII碼或狀態信息,一起存儲到內存的指定空間(鍵盤緩沖區或狀態字節)中。
??????其中鍵盤緩沖區一共有16個字單元,可以存儲15個按鍵的掃描碼和對應的ASCII碼。這是因為采用了循環隊列來實現的,會有一個單元被浪費掉。
??????例如:當摁下 A、B、C、shift_A、A 時鍵盤緩沖區的狀態如下:
??????當摁下 A 鍵時,int 9 例程從 60h 端口讀取A鍵的通碼;檢測狀態字節判斷是否有控制鍵(Ctrl、Shift)按下,發現沒有被按下時,將A鍵的掃描碼 1eh 和對應的字母 ’a’ 的ASCII碼 61h寫入鍵盤緩沖區中。高位字節存儲掃描碼,低位字節存儲ASCII碼。
??????當摁下 B、C 鍵時進行類似的操作。
??????當摁下 Shift_A 鍵時,(1)當按下左 Shift 鍵時,發生鍵盤中斷,int 9 中斷例程接收左 Shift 鍵的通碼,設置 0040:17 處的狀態字節的第1位為1,表示左 Shift 鍵按下。(2)當按下 A 鍵時,int 9 例程從 60h 端口讀出A鍵的通碼;檢測狀態字節發現左 Shift 鍵按下,則將 A 鍵的掃描碼 1Eh 和 Shift_A 對應的大寫字母 ‘A’ 的ASCII碼 41h 寫入鍵盤緩沖區。(3)當松開左 Shift 鍵時,發生鍵盤中斷,int 9 中斷例程接收左 Shift 鍵的斷碼,設置0040:17處的狀態字節的第1位為0,表示左 Shift 鍵松開。
??????最后再次按下 A 鍵時的操作同上。
????????????????????????????????????????????????????????????5次按鍵的鍵盤緩沖區圖示
| 1, | 1E61 | |||||||||||||||
| 2, | 1E61 | 3062 | ||||||||||||||
| 3, | 1E61 | 3062 | 2E63 | |||||||||||||
| 4, | 1E61 | 3062 | 2E63 | 1E41 | ||||||||||||
| 5, | 1E61 | 3062 | 2E63 | 1E41 | 1E61 |
??????2,使用 int 16h 中斷例程的 0 號子程序可以從鍵盤緩沖區中讀取一個鍵盤輸入,并將其從緩沖區中刪除。具體步驟如下:
??????(1)檢測鍵盤緩沖區中是否有數據。
??????(2)沒有則繼續做第1步。即一直在等待,等待有數據被輸入到鍵盤緩沖區中。
??????(3)讀取緩沖區中最早進入的鍵盤輸入,從隊頭開始讀取。
??????(4)將讀取的掃描碼送入 ah,ASCII碼送入 al。
??????(5)將已讀取的鍵盤輸入從緩沖區中刪除。
??????對上面的鍵盤緩沖區執行:
??????緩沖區中的結果為
| 3062 | 2E63 | 1E41 | 1E61 |
??????ah 中的內容為 1eh,al 中的內容為 61h。
??????總結:int 9 和 int 16h 可以相互配合使用,int 9 是在有鍵按下的時候向鍵盤緩沖區中寫入數據,int 16h 是在應用程序對其進行調用的時候,將數據從鍵盤緩沖區中讀出。當我們需要對某一個特定的按鍵實現一個特別的功能時,有兩種方法,一種是通過 Int 9 中斷例程在處理鍵盤輸入時來實現;另一種是通過調用 int 16h 從鍵盤緩沖區中讀取鍵盤輸入來實現。后者的優點在于不需要重寫編寫 int 9 中斷例程。
練習1
??????編寫程序,接收用戶的鍵盤輸入,輸入 ‘r’,將屏幕上的字符設置為紅色;輸入 ’g‘,將將屏幕上的字符設置為綠色;輸入 ’b’,將屏幕上的字符設置為藍色。
??????關于在屏幕上顯示顏色的細節可參考??????https://blog.csdn.net/Little_ant_/article/details/108227058
練習2
??????編寫字符串輸入程序,需具備下面的功能。
??????(1)在輸入的同時需要顯示這個字符串。
??????(2)一般在輸入回車符后,字符串輸入結束。
??????(3)能夠刪除已經輸入的字符。
??????因為需要顯示字符串,故,子程序的參數為:(dh)、(dl) = 字符串在屏幕上顯示的行、列位置;ds:si 指向字符串的存儲空間,字符串以0為結尾符。
??????首先,我們采用棧的方式來管理字符串的存儲空間,即字符串的存儲空間實際上是一個字符棧。輸入字符時,字符入棧;刪除字符時,字符出棧;顯示字符時,從棧底到棧頂來顯示。其次,輸入回車符后,可以在字符串中加入 0,表示字符串結束。最后,每次當有新的字符輸入或刪除字符時,都應該重新顯示該字符串。
??????程序的處理過程如下:
??????1,調用 int 16h 讀取鍵盤輸入
??????2,如果是字符,進入字符棧,顯示字符棧中的所有字符,繼續執行 1。
??????3,如果是退格鍵,從字符棧中彈出一個字符,顯示字符棧中的所有字符,繼續執行1。
??????4,如果是回車鍵,向字符棧中壓入 0,返回。
??????因為包含多次字符入棧、出棧和顯示,我們將它們編寫為子程序。
其中用(ah)=功能號,0 表示入棧、1 表示出棧、2 表示顯示。用ds:si 指向字符棧空間。在入棧時,(al)= 入棧字符;出棧時,(al)= 出棧字符;顯示時,(dh)、(dl)為屏幕上顯示的行、列位置。
??????編寫完整的接受字符串輸入的子程序如下:(注意:在顯示棧中字符的時候,需要清除屏幕上一次顯示的內容):
getstr: push axgetstrs: mov ah,0int 16h ;接收鍵盤輸入,ah中放掃描碼,al中放字符碼cmp al,20hjb nochar ;ASCII碼小于20h,說明不是字符mov ah,0call charstack ;存放在(al)中的字符入棧,ah表示調用0號子程序mov ah,2call charstack ;顯示棧中的字符串jmp short getstrsnochar: cmp ah,0eh ;退格鍵的掃描碼je backspacecmp ah,1ch ;回車鍵的掃描碼je enterjmp short getstrsbackspace: mov ah,1call charstack ;字符出棧mov ah,2call charstack ;顯示棧中字符jmp short getstrsenter: mov al,0mov ah,0call charstack ;將0入棧mov ah,2call cahrstack ;顯示棧中的字符pop ax ;退出ret總結
以上是生活随笔為你收集整理的汇编语言随笔(15)- 对键盘输入进行处理(int 9 和 int 16h 中断例程)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 汇编语言随笔(14)-直接定址表、检测点
- 下一篇: 汇编语言随笔(16)- 对磁盘进行读写(