汇编实验:自定义键盘中断的处理函数

汇编实验报告-键盘中断

1. 实验任务:采用键盘中断方式,当输入是字符或数字的时候,回显输入并回车换行;否则退出。

2. 运行环境:Windows11+MASM

3. 题目分析:

在课上我们刚刚学习了中断的概念以及自定义中断,且有一个例程是对键盘中断进行获取的。因此我们可以借鉴例程,通过mov ah 25h/35h完成对键盘中断的存取和设置,获取键入的字符。

但是最开始想直接输出获取的字符却发现均为乱码,查询后才发现由键盘中断方式读取的是字符的扫描码,该码与ASCII码不同,是键盘上第一排“0-9,-=”有邻近的扫描码,第二排“qwertyuiop[]|”有邻近的扫描码等等。于是我们找到扫描码和字符的对应表,手动创建一个字符串,存储从00H-39H的所有字符,如果不是可显示字符,或是控制字符,就用#代替。通过这种方式可以把扫描码直接映射到对应字符的ASCII码输出。

4. 流程图绘制:根据分析和题目要求绘制主函数的流程图:

image-20221102163732393

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接受扫描码,然后与数据段中我们定义的字符串偏移量匹配,如果是#则放弃输出,否则判断为正确字符、输出该字符。
  • 流程图
    image-20221103220126967
  • 程序段代码如下:
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

    主函数的作用是设置中断向量,并且进行延时,等待中断程序的调用。

  • 流程图

    image-20221103212731936
  • 程序段代码如下:

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数字排的输出

    image-20221103213913472

  2. 三个字母排的输出

    image-20221103214113321

可见功能正常,成功实现。

  1. 现存问题:由于我们认为SHIFT是不合法的字符,因此我们无法实现SHIFT+小写字母输出大写字母的功能。
posted @ 2022-11-29 15:17  丘丘王  阅读(177)  评论(0编辑  收藏  举报
鼠标点击页面特效

尝试在空白处点击鼠标