我想编写一个程序,按三个键结束:大写锁定,nom锁定和左移。我可以使用AH = 02h,INT 16h来检查它们是否被压在一起? 我可以使用哪些其他中断? 好奇:)
这是我的代码,但我不同意这个中断是如何工作的:
TITLE 'PressKeys' ;key program
;-----------------------------------------------------------------------------------
;DATA SEGMENT
DASEG SEGMENT PARA PUBLIC 'data'
CHECK DB 01100010b;The number which is used to check the control keys
;in the INT 16H (caps lock,nom lock,left shoft)
MESG DB 'FINISH $';Massage to say finish
DASEG ENDS
;--------------------------------------------------------------------------------------
;CODE SEGMENT
COSEG SEGMENT PARA PUBLIC 'code'
ASSUME CS:COSEG, DS:DASEG, ES:NOTHING, SS:NOTHING
MAIN:
MOV AX,DASEG
MOV DS,AX
;Check if the caps and nom and left shift keys has been pressed
KLOOP:
MOV AH,02H
INT 16H
TEST AL,CHECK
Jnz PRESSED ;If the keys has been pressed finish the programm
JMP KLOOP
PRESSED:;PRINT MESSAGE
LEA DX,MESG
MOV AH,09H
INT 21H
;GET BACK TO OS
MOV AX,4C00H
INT 21H
COSEG ENDS
;------------------------------------------------------------------------------
;END OF PROGRAMM
END MAIN
答案 0 :(得分:1)
int 16h / 2检查BIOS数据区中的一个字节 - 40h:17h(我必须检查RBIL以记住该地址)。您可以自己检查该字节,但中断可能更容易。
test
指令通常仅在第二个操作数中设置一个位。如果你正在做test
多个比特,如果设置了三个比特中的任何一个,你就会得到NZ。使用test
三次 - 一次一位,或and al
使用您的值,然后cmp
使用精确值来查看是否已设置所有三位。
编辑:更多信息:当按下某个键时,再次释放该键时,会生成一个IRQ。这由中断服务程序处理,通常是int 9.在大多数情况下,忽略“释放”中断。在少数情况下,我们需要“记住”按键已被按下而未被释放(“转换”是最明显的)。这是通过在BDA中设置(或清除)几个字节中的位来完成的。 (80键键盘只有1个字节 - 来自博物馆)
int 16h
- “键盘中断” - 实际上不靠近键盘控制器(由int 9
处理)但与BDA中的某些字节相互作用 - “移位标记”你'感兴趣的是,“键盘缓冲区”和几个字节 - “头指针”和“尾指针”进入缓冲区(如果它们相同,没有密钥可用)。
所以int 16h/2
将返回40h时字节中设置的内容:17h - 使用`int 16h / 12h得到“扩展移位标志” - 两个字节 - 如果你需要它们。在你给出的例子中 - 01011001是吗? (我无法从“编辑模式”看到你的评论) - 我认为有些位表示“活跃”而不是“按下”,所以它可能不会做你想要的。请注意,只有“某些键”保存了其按下/释放状态。
你通过中断做得很好,但是如果按下任何一个键,你使用test
指令的方式将指示“按下”。我知道你要检查“全部三个”。见上文。
拉尔夫·布朗的中断名单 - RBIL - 拥有所有这些信息。如果你下载整个混乱,而不是咨询在线版本,有“ports.lst”,“memory.lst”和一堆其他信息。我强烈建议你明白......如果你要浪费时间使用16位代码。 :)
答案 1 :(得分:0)
我认为你最好写这个:
...
OR AL, 10011101B
CMP AL, 11111111B
JC KLOOP
...
无论按下这三个键中有多少个键,您的代码都可以跳转到PRESSED。按下至少一个键会导致成功,这显然不是你的意图。 看看结果如何受JNZ影响,因此导致跳转到PRESSED,这是不正确的:
TEST AL, 01100010B
AL = 01000000 -> Result NOT Zero
AL = 00100000 -> Result NOT Zero
AL = 00000010 -> Result NOT Zero
重要的是,AND,OR和TEST指令是逐位的,即它们是逐位AND和OR两个操作数。所以在上面的例子中,整个结果仍然大于零。 然而,你使用TEST而不是AND有助于保留AL中的原始值,并且是一个很好的习惯。