PC机键盘的处理过程(外中断

您所在的位置:网站首页 ibmpc是一台 PC机键盘的处理过程(外中断

PC机键盘的处理过程(外中断

2023-08-19 23:45| 来源: 网络整理| 查看: 265

我们知道cpu在计算机系统中除了能够执行指令,进行运算以外,还应该能对外部设备进行控制,接收它们的输入,向它们进行输出,也就是说cpu除了具有运算能力外,还要有I/O(Input/Output,输入输出)能力。通过以前的学习我们知道,PC系统的接口卡和主板上装有各种接口芯片。这些外设接口芯片的内部有若干寄存器,cpu将这些寄存器当作端口来访问。

外设的输入不直接送入内存和cpu,而是送入相关的接口芯片的端口中,cpu向外设的输出也不是直接送入外设,而是先送入端口中,再由相关的芯片送到外设。cpu还可以向外设输出控制命令,而这些控制命令也是先送到相关芯片的端口中,然后再由相关的芯片根据命令对外设实施控制。可见cpu通过端口和外部设备进行联系。

至此,我们知道了外设的输入被存放在端口中,可是外设的输入随时都有可能到达,cpu如何及时的知道并进行处理呢?这就用到了我们今天的主角-中断机制。cpu提供中断机制来满足这种需要,当cpu的内部有需要处理的事情发生时,将产生中断信息,引发中断过程,这种中断信息来自cpu内部,还有一种中断信息,来自于cpu外部,当cpu外部有需要处理的事情发生的时候,比如说,外设的输入到达,相关芯片将向cpu发出相应的中断信息。cpu在执行完当前指令后,可以检测到发送过来的中断信息,引发中断过程,处理外设的输入。

PC机处理键盘输入的过程如下:

1、键盘输入

键盘上的每一个按键相当于一个开关,键盘中有一个芯片对键盘上的每一个键的开关状态进行扫描,按下一个键时,开关接通, 该芯片就产生一个扫描码,扫描码说明了按下的键在键盘上的位置。扫描码被送入主板上的相关芯片的寄存器中,该寄存器的 端口地址为60h。松开按下的键时,也产生一个扫描码, 扫描码说明了松开的键在键盘上的位置,松开按键时产生的扫描码也 被送入60端口中。一般我们将按下一个键时产生的扫描码称为通码,松开一个按键产生的扫描码称为断码。扫描码长度为一个 字节,通码的第七位为0,断码的第七位为1,即断码 = 通码 + 80h。

2、引发9号中断

键盘的输入到达60端口时,相关的芯片就会向cpu发出中断类型码为9的可屏蔽中断信息。cpu检测到改中断信息后,如果IF = 1 ,则响应中断,引发中断过程,转去执行int 9中断例程。

3、执行int9中断例程

BIOS提供了int 9中断例程,用来进行基本的键盘输入处理,主要的动作如下: (1)读出60端口中的扫描码; (2)如果是字符键的扫描码,将该扫描码和它所对应的字符码即ASCII码送入内存中的BIOS键盘缓冲区;如果是控制键(如ctrl) 和切换键(如CapsLock)的扫描码,则将其转变为状态字节(用二进制位记录控制键和切换键状态的字节)写入内存中存储 状态字节的单元; (3)对键盘系统进行相关的控制,比如说,向相关芯片发出应答信息。 BIOS键盘缓冲区是系统启动后,BIOS用于存放int 9号中断例程所接受的键盘输入的内存区。该内存区可以存储15个键盘输入,因为int 9中断例程除了接受扫描码外,还要产生和扫描码对应的字符码,所以在BIOS键盘缓冲区中,一个键盘输入用一个字单元存放,高位字节存放扫描码,低位字节存放字符码。 0040:17单元存储键盘状态字节,该字节记录了控制键和切换键的状态。键盘状态字节各位记录的信息如下:

由以上内容我们知道,键盘输入的处理过程: 1、键盘上的芯片产生扫描码,2、扫描码被送入60端口,3、引导9号中断;4、cpu执行int9中断例程处理键盘输入 在上面的过程中,前3步都是由硬件系统完成的。我们能改变的只有int 9中断处理程序。我们可以重新编写int9中断例程。按照 自己的意图来处理键盘的输入,因为一个完整的键盘输入的处理要涉及一些硬件细节,针对这种情况,我们可以在自己编写的中 断例程中调用BIOS的int9中断例程帮我们处理。

编程:在屏幕中间依次显示"a"~“z”,并可以让人看清。在显示的过程中,按下Esc键后,改变显示的颜色。 依次显示"a"~"z"的代码如下:

assume cs:code code segment start:mov ax, 0b800h mov es, ax mov ah, 'a' s1: mov es:[160*12+40*2], ah inc ah cmp ah, 'z' jna s1 mov ax, 4c00h int 21h code ends end start

在上面代码的执行过程中,我们无法看清屏幕上字符的变化,因为cpu执行太快导致字符切换过快,因此我们想办法在每显示一个 字符后延时一段时间,让人看清后再显示下一个字符,这里我们实现一个延时的子程序供主程序调用,代码如下:

delay: push ax push dx mov ax, 0 mov dx, 1000h ;//cpu循环执行10000 000h次 s2:sub ax, 1 sbb dx, 0 cmp ax, 0 jne s2 cmp dx, 0 jne s2 pop dx pop ax ret

那如何改变颜色呢? 键盘输入到达端口后,就会引发9号中断,cpu转去执行int9中断例程。我们可以编写int9中断例程,功能如下: (1)从60端口中读出键盘的输入; (2)调用BIOS的int9中断例程,处理其他硬件细节; (3)判断按键是否为Esc的扫描码,如果是,则改变显示的颜色后返回;如果不是则直接返回。 下面我们分步实现以上步骤

1、从60端口中读出键盘的输入 in al, 60h 2、调用BIOS的int9中断例程

有一点我们要注意,在我们编写好int9中断例程后,主程序必须将中断向量表中的int9中断例程的入口地址改为我们新写的中断 处理程序的入口地址,但是在新的中断处理程序中调用原来的int9中断例程时,中断向量表中的int9号中断例程的入口地址已不 是原来的int9中断例程的地址,所以我们不能使用int指令直接调用。 要能在我们新写的中断例程中调用原来的中断例程,就必须在将中断向量表中的中断例程的入口地址改为新地址之前,将原来的 入口地址保存起来,这样在需要调用的时候才能找到。

保存了入口地址后,该如何调用呢? 当然不能使用指令int9来调用,我们可以使用别的指令来对int指令进行模拟,从而实现对中断例程的调用。 我们知道,int指令在执行的时候,cpu进行下面的工作。 (1)取中断类型码n; (2)标志寄存器入栈 (3)IF=0,TF=0; (4)CS、IP入栈 (5)(IP)=(n4), (CS=n4+2) 取中断类型码是为了定位中断例程的入口地址,在我们自己写的中断例程中已知道地址,因此不需要做第一步,假设要调用的中断 例程的入口地址被保存在ds:0和ds:2单元,我们将用以下步骤来模拟int过程 (1)标志寄存器入栈 (2)IF=0,TF=0; (3)CS、IP入栈 (4)(IP)=(ds16+0), (CS=ds16+2) 注意到第三步和第四步的功能和call dword ptr ds:[0]的功能一样,call dword ptr ds:[0]的功能也是 push cs, push ip, (IP)=(ds16+0), (CS=ds16+2),所以int的模拟过程变为: (1)标志寄存器入栈 (2)IF=0,TF=0 (3)call dword ptr ds:[0] 对于上面步骤一可用pushf实现。对于步骤二可用下面的指令来实现

pushf pop bx and bh, 11111100B push bx popf ;IF=0, TF=0 ;CS, IP入栈,IP = n*4, CS = n*4+2 call dword ptr ds:[0] ;对int指令进行模拟,调用原来的int 9中断例程 3、如果是Esc按键的扫描码,改变显示的颜色后返回

如何改变现实的颜色呢? 显示的位置是在屏幕的中间,即第12行40列,显存中的偏移地址为:16012+402。所以字符的ASCII码要送入段地址b800h,偏移 地址16012+402处。而段地址b800h偏移地址16012+402+1处时字符的属性,我们只要改变此处的数据就可以改变显示字符的颜色 该程序的最后一个问题是,要在程序返回前,将中断向量表中的int9号中断例程的入口地址恢复为原来的地址。否则程序返回后, 别的程序将无法使用键盘。 经以上分析,完整源码如下:

assume cs:code stack segment db 128 dup (0) stack ends data segment dw 0, 0 data ends code segment start:mov ax, stack mov ss, ax mov sp, 128 mov ax, data mov ds, ax ;保存原有int 9号中断处理程序的入口地址 mov ax, 0 mov es, ax push es:[9*4] pop ds:[0] push es:[9*4+2] pop ds:[2] mov word ptr es:[9*4], offset int9 mov es:[9*4+2], cs mov ax, 0b800h mov es, ax mov ah, 'a' s1: mov es:[160*12+40*2], ah call delay inc ah cmp ah, 'z' jna s1 ;为了不影响后续的键盘输入处理,需要将int 9号中断处理程序的入口地址恢复为原来的地址 push ds:[0] pop es:[9*4] push ds:[2] pop es:[9*4+2] mov ax, 4c00h int 21h delay:push ax push dx mov ax, 0 mov dx, 1000h ;//cpu循环执行10000 000h次 s2:sub ax, 1 sbb dx, 0 cmp ax, 0 jne s2 cmp dx, 0 jne s2 pop dx pop ax ret ;-----------新的int 9中断例程------------- int9: push ax push bx push es in al, 60h ;从端口60h读出键盘的输入 pushf ;标志寄存器入栈 ;设置IF = 0, TF = 0 pushf pop bx and bh, 11111100B push bx popf ;CS, IP入栈,IP = n*4, CS = n*4+2 call dword ptr ds:[0] ;对int指令进行模拟,调用原来的int 9中断例程 cmp al, 1 ;esc键的扫描码为1 jne int9ret mov ax, 0b800h mov es, ax inc byte ptr es:[160*12+40*2 + 1] ;属性值加1改变颜色 int9ret:pop es pop bx pop ax iret code ends end start

程序运行图示如下: 在这里插入图片描述 注意,本文中所有关于键盘的程序,因为要直接访问真实的硬件,则必须在DOS实模式下运行。在Windows2000的DOS方式下运行, 会出现一些和硬件工作原理不符合的现象。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3