使用BIOS进行键盘输入

使用BIOS进行键盘输入


大多数有用的程序都需要处理用户的输入,键盘输入是最基本的输入,程序和数据需要长期存储,BIOS为这种外设的I/O提供了最基本的中断例程

int 9中断例程对键盘输入的处理

键盘输入将引发9号中断,BIOS提供了int 9中断例程,CPU在9号中断发生后,执行int 9中断例程,从60h端口读出扫描码,并将其转化为相应的ASCII码或状态信息,存储在内存的指定空间(键盘缓冲区或状态字节)中
下面,我们通过下面几个键:
A,B,C,D,E,shift_A的输入过程,简要地看一下int9中断例程对键盘输入的处理方法

  1. 初始状态下,没有键盘输入,键盘缓冲区空,此时没有任何元素
  1. 按下A键,引发键盘中断,CPU执行int 9中断例程,从60h端口读出A键的通码,然后检测状态字节,看看是否有shift,ctrl等切换键按下,发现没有切换键按下,则将A键的扫描码1eh和对应的ASCII码,即字母"a"的ASCII码61h,写入键盘缓存区,缓冲区的字单元中,高位字节存储扫描码,低位字节存储ASCII码,此时缓冲区的内容为:
1E61
  1. 按下B键,引发键盘中断,CPU执行int 9中断例程,从60h端口读出B键的通码,然后检测状态字节,看看是否有切换键按下,发现没有切换键按下,将B键的扫描码30h和对应的ASCII码,即字母"b"的ASCII码62h,写入键盘缓冲区,此时缓冲区中的内容如下
1E61 3062
  1. 按下C,D,E键后,缓冲区中的内容为:
1E61 3062 2E63 2064 1265
  1. 按下左Shift键,引发键盘中断,int 9中断例程接收左Shift键的通码,设置0040:17处的状态字节的第1位为1,表示左Shift键按下
  2. 按下A键,引发键盘中断,CPU执行int 9中断例程,从60h端口读出A键的通码,检测状态字节,看看是否有切换键按下,发现左Shift键按下,则将A键的扫描码1Eh和shift_A对应的ASCII码,即字母"A"的ASCII码41h,写入键盘缓冲区,此时键盘缓存区中的内容如下
1E61 3062 2E63 2064 1265 1E41

使用int 16h中断例程读取键盘缓冲区

BIOS提供了int 16h中断例程供程序员调用,int 16h中断例程中包含的一个最重要的功能是从键盘缓冲区中读取一个键盘输入,该功能的编号为0,下面的指令从键盘缓冲区中读取一个键盘输入,并且将其从缓冲区中删除

mov ah,0
mov 16h

结果:(ah)=扫描码,(al)=ASCII码

  1. 执行
mov ah,0
int 16h

后,缓冲区中的内容如下:

3062 2E63 2064 1265 1E41

ah中的内容为1Eh,al中的内容为61h

  1. 执行
mov ah,0
int 16h

后,缓冲区中的内容如下:

2E63 2064 1265 1E41

ah中的内容为30h,al中的内容为62h

  1. 执行4次
mov ah,0
int 16h

后,缓冲区为空

  1. 执行
mov ah,0
int 16h

int 16h中断例程检测键盘缓冲区,发现缓冲区空,则循环等待,直到缓冲区中有数据

  1. 按下A键后,缓冲区中的内容如下:
1E61
  1. 循环等待的int 16h中断例程检测到键盘缓冲区中有数据,将其读出,缓冲区又为空

从上面我们可以看到,int 16h中断例程的0号功能,进行如下的工作

  1. 检测键盘缓冲区中是否有数据
  2. 没有则继续做第1步
  3. 读取缓冲区第一个字单元中的键盘输入
  4. 将读取的扫描码送入ah,ASCII码送入al
  5. 将已读取的键盘输入从缓冲区中删除

可见,BIOS的int 9中断例程和int 16h中断例程是一对相互配合的程序,它们的写入和读取的时机不同,int 9中断例程是在有键按下的时候向键盘缓冲区中写入数据,而int 16h中断例程是在应用程序对其进行调用的时候,将数据从键盘缓冲区中读出

上一篇:BIOS报警声


下一篇:Ubuntu 16.04将UTC改CST不生效分析及解决方式