1. 程式人生 > 其它 >彙編實驗:自定義鍵盤中斷的處理函式

彙編實驗:自定義鍵盤中斷的處理函式

彙編實驗報告-鍵盤中斷

1. 實驗任務:採用鍵盤中斷方式,當輸入是字元或數字的時候,回顯輸入並回車換行;否則退出。

2. 執行環境:Windows11+MASM

3. 題目分析:

在課上我們剛剛學習了中斷的概念以及自定義中斷,且有一個例程是對鍵盤中斷進行獲取的。因此我們可以借鑑例程,通過mov ah 25h/35h完成對鍵盤中斷的存取和設定,獲取鍵入的字元。

但是最開始想直接輸出獲取的字元卻發現均為亂碼,查詢後才發現由鍵盤中斷方式讀取的是字元的掃描碼,該碼與ASCII碼不同,是鍵盤上第一排“0-9,-=”有鄰近的掃描碼,第二排“qwertyuiop[]|”有鄰近的掃描碼等等。於是我們找到掃描碼和字元的對應表,手動建立一個字串,儲存從00H-39H的所有字元,如果不是可顯示字元,或是控制字元,就用#代替。通過這種方式可以把掃描碼直接對映到對應字元的ASCII碼輸出。

4. 流程圖繪製:根據分析和題目要求繪製主函式的流程圖:

5. 各部分與功能的流程圖/程式:

  1. 資料段定義:當我們定義資料段時,我們要考慮的有以下幾方面因素:
  • 由於設定中斷前必須儲存原有中斷處理函式,結束後必須恢復原中斷,因此需要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
  1. 中斷處理函式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
  1. 主函式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.執行結果

  1. 0-9數字排的輸出

  2. 三個字母排的輸出

可見功能正常,成功實現。

  1. 現存問題:由於我們認為SHIFT是不合法的字元,因此我們無法實現SHIFT+小寫字母輸出大寫字母的功能。