键盘上的每一个键相当于一个开关,键盘中有一个芯片,对键盘上的开关状态进行扫描。当按下一个按键的时候,开关接通,该芯片产生一个扫描码
,扫描码
说明了按下的键在键盘的位置。
扫描码被送到主板上的相关接口芯片的寄存器中,该寄存器的端口地址为60h
。松开按键的时候,也会产生一个扫描码,这个扫描码说明松开的按键在键盘的位置,这个扫描码也会被送入60h
端口。
通常按键产生的码叫做 通码
,而松开产生的码叫做 断码
。扫描码的长度是1个字节。通码的第7位是0,断码的第7位是1.
断码 = 通码+ 80h
当键盘的输入到达60h端口后,芯片就会向CPU发出中断类型码为9
的可屏蔽中断
,
bios提供了应用来处理键盘的输入,工作流程如下
读取60h端口的数据
如果是字符键的扫描码,则将扫描码和对应的assic字符送入bios的键盘缓冲区,如果是控制字符(例如ctrl),将其转换成状态字节(用二进制位记录控制键和切换键状态的字节)写入到内存中存储状态字节的单元。
对键盘系统进行相关的控制,例如向芯片发出应答信息。
bios键盘缓冲区是系统启动后,是bios用来存储int 9中断的输入的内存区域,该区域可以存放15键盘输入,int 9除了接受码以外,还要产生码对应的字符,所以bios的键盘缓冲区,键盘输入用一个字节单元,高位放扫描码,低位放字符码。
0040:17 单元存放键盘状态字节,该字节记录了控制键和切换键的状态键盘状态字节各位记录的信息。
编程将a-z字符显示在屏幕中央,通过esc变换颜色。
assume cs:code
stack segment
dp 128 dup (0); 定义128的字节的空间
stack ends
code segment
start: mov ax,0b800h
mov es,ax; 设置屏幕显示地址
mov ah, 'a'
s: mov es:[160*12+40*2], ah; 设置ah中的字母
call delay; 避免转瞬即逝
inc ah; 下一个字符
cmp ah,'z'
jna s; 不是z的时候要继续执行
mov ax,4c00h
int 21h
delay: push ax
push dx
mov dx,1000h
mov ax,0
s1: sub ax,1
sbb dx,0
cmp ax,0
jne s1
cmp dx,0
jne s1
pop dx
pop ax
ret
code ends
end start
实现键盘输入部分
这部分代码需要变成新的int 9中断处理程序,这段代码会修改int 9中断向量表中的程序入口。
如果要在9号中断的位置设置新的程序,需要将原来的保存起来,这样,在调用的时候才能找得到。例如将9号中断位置的内容保存到ds:[0], ds:[1]的位置。
这里需要模拟int 9的动作。因为已经知道中断码,只需要从压栈标志寄存器即可。