键盘与主机之间通过几个端口互相通信,其中对于编写键盘中断服务程序来说比较重要的是端口60H和61H。61H端口在前文讨论发声时已经介绍过它Bit0与Bit1两位,主机通过这个端口的最高位Bit7给键盘发送"应答(ECHO)"信号。
当键盘有一个键按下时,键盘会首先将按键的扫描码送进60H端口,然后发出中断信号并等待主机回答。CPU在收到中断信号并取得扫描码之后必须要告诉键盘这个键的扫描码已经取到,如果CPU不给出回应,那么键盘就不会处理其它按下的键,因为键盘认为前一个键的扫描码主机还没有收到,此时发出新的扫描码会冲掉上一个按键的扫描码。
产生应答信号的方法也很简单,只要让61H端口Bit7位从1到0产生一个变化就行了。这实际是使这一位的电压从高到低产生一个跳跃,键盘会检测到这个变化并开始处理下一个按键。
由于PC电脑连接的各种硬件设备其工作速度有很大差异,所以CPU对各设备发出的硬件中断的处理是排有一定顺序,这种顺序一般称为中断优先级。所以当几个硬件中断同时发生时,优先级别高的中断会被CPU首先处理。
不过由于系统原理上的一些原因,PC电脑要求当一个硬件中断得到CPU响应后,其服务程序必须要向"中断控制电路"发出一个"中断结束命令(EOI)",否则"中断控制电路"就会屏蔽与正在处理的中断同优先级或低优先级的其它硬件中断。这样一来其它外设即使发出中断信号也得不到CPU的服务,因为这个信号根本送不到CPU那里。发出EOI命令的方法并不难,只要向20H端口送出数据20H即可。
设置新的中断服务程序入口并不是只有一种方法,可以直接将新的服务程序入口地址填入中断向量表的正确位置,也可以采用DOS提供的系统功能调用。这个功能的功能号是25H:
功能号:25H
用 途:设置中断服务程序入口地址
参 数:AH=25H
AL=中断号
DS:DX=新的中断服务程序入口地址
调 用:INT 21H
返 回:无
我们一般提倡使用系统功能调用设置中断服务程序入口,这样做有利于增强程序的可移植性。
还有一点需要注意的是在进入中断服务程序之后首先要保存一些需要使用的寄存器,在服务程序结束时再恢复这些寄存器的原值。这样可以保证被中断的程序能正确的运行。
给出的示例程序虽然能够正确地处理F11和F12两个功能键,但是它有一个致命的缺陷,就是除了F11和F12两键之外,其它的键全部"罢工"了。
我们编制的这个中断服务程序比较的简单,它只能处理F11和F12两个键,而不能处理其它的键。不过当我们在中断向量表中重新设定09H中断服务程序的入口后,这个不完善的中断服务程序就完全接管了键盘。这相当于我们彻底推翻了原09H中断服务程序的"专制统治",建立了一个"共和政府"。遗憾的是这个"共和政府"的领导者"NEW09"的能力实在是有限,根本领导不了键盘上的"全体人民"。
如果需要保持键盘的原功能,那么就需要编制一个很完善的09H中断服务程序,这样做的工作量是很大的。难道非这样做不可吗?
其实原来的09H中断服务程序虽然"专制",但是它的能力还是比较强的。试想如果我们不"完全推翻"原09H中断服务程序,而是让"NEW09"与原来的服务程序组成一个"君主立宪"政府,由原09H中断服务程序负责键盘上多数"人民",由"NEW09"负责F11与F12这两个"少数民族",互相合作,这样就能保持键盘的原功能了。