键盘输入程序是整个程序最复杂的部分.这个程序决定了下个送给DOS的字符是什么.如果扩充字符送完时,就调用旧的键盘输入程序取得下一个输入的字符.无论从键盘输入的字符是什么,都必须检查是否是希望扩充的字符.键盘输入程序是把输入的结果放在寄存器AL中.如果输入的字符是增加字符时(如F1),那么AL的内容是0,增加的字符码则放在AH中.
如果读到的字符是希望扩充的字符F1,那么就必须开始进行扩充工作.这时候就必须把指针current指到扩充字符串的开头.大多数人常犯的一个错误是:使用mov cs:current,string而不是mov cs:current,offset string.这两者的差别在于前者是错误的,因为它的意思是把一个字节的内容移到一个字节之中,汇编器会强迫两者的形式吻合.后者则是正确的,因为 我们希望做的是把式string指向的地址值移到current之中.
当我们在进行扩充时,就把指针current所指的字节内容移到AL中,只要AL的内容不是0,就不必管AH的内容是什么.如果AL是0的话,就表示已经到了扩充字符的结尾了.这表示不应该传回0,而必须重新调用Old_Keyboard_IO ,以便从键盘取得输入字符.
在程序包KeyRead中有一行指令比较特殊,你也许注意到了,在进入KeyRead,当确定current为0时,接下来又把current设定成0.这样做虽然有些奇怪,却没有任何伤害;但是对于扩充字符串到达结尾时,却很有用.当我们到达扩充字符串的结尾时,current的内容将指到字符串结尾的下一个位置,而不是0.因此必把current设定为0,可以先跳到某一位置把current设定为0,然后再跳到ReadChar.而采取前面程序的做法时,只是浪费一行毫无伤害的指令,却可以使程序变得简明.
在这个程序中,每次使用到内存的内容时,都必须牵涉到段值,这一点相当重要.当计算机的控制权转移到我们的程序中时,我们对于DS的内容是不知道的.但是有两件事可以确定:第一,DS的内容对我们的程序几乎没有任何用;第二,DS的内容对于被中断的程序可能很重要.因此我们必须保证每次使用到内存位置时,都是使用目前的段,亦即以目前的CS值为标准.必须要确定:如果使用到任何寄存器的话那么在程序结束前,必须恢复其值.
5.2 多键扩充程序
上面的程序是把某一个特殊键扩充成一个字符串.如果要把一组特殊键扩充成其个别的扩充字符串,该如何做呢?
一个比较常见的做法是,修改上面的程序,让它接受被扩充字符以被扩充字符串为参数.譬如,如果这个程序名为MACRO,那么可以在AUTOEXEC.BAT中定义以下的指令:
..
MACRO F1 DIR
MACRO F2 DIR/W
MACRO F3 DIR *.ASM
MACRO F4 DIR *.COM
MACRO F5 DIR *.EXE
..
这种做法是把MACRO这程序一个个留在内存中,至于每一个所做的