我正在用程序集8086编写游戏。解决了游戏无法打开时的问题,但无法修复控件。
ESC键起作用。当我按下它时,它将转到_QUIT函数,但是如果在此之前按下了任何其他键,则控件将冻结并且不会对任何键作出反应。
我的功能有问题吗?
我试图将AL
寄存器更改为AH
,但是没有用。
_KEYCHECK:
mov ah,01h
int 16h
cmp al,1Bh ;ESC
je _QUIT
cmp al,48h ;UP
je _PLAYER.UP
cmp al,50h ;DOWN
je _PLAYER.DOWN
cmp al,4Bh ;LEFT
je _PLAYER.LEFT
cmp al,4Dh ;RIGHT
je _PLAYER.RIGHT
ret
最佳答案
您的_KEYCHECK函数正在使用BIOS.ReadKeyboardStatus函数。
如果没有可用的按键,它将通过设置ZeroFlag(ZF)来通知您有关键盘按键的可用性,或者如果有按键正在等待,则将其清零。在后一种情况下,您还将收到密钥的ASCII码和scancode。
这里重要的是,报告的可用键保留在键盘缓冲区中。在AL
和AH
中获得的信息只是预览,而不是实际的键(在某种意义上)。这解释了您的观察:
...但是如果在此之前按下了其他任何键,则控件将释放...
解决方案是从键盘缓冲区中删除键。这就是BIOS.ReadKeyboardCharacter所做的。如果某个键在等待,它将很快从缓冲区中移出该键。如果没有可用的密钥,它将等待,直到有一个可用的密钥,然后再从缓冲区中删除该密钥。
_KEYCHECK:
mov ah, 01h ; BIOS.ReadKeyboardStatus
int 16h ; -> AX ZF
jz NoKeyAvailable
mov ah, 00h ; BIOS.ReadKeyboardCharacter
int 16h ; -> AX
cmp al, 1Bh ;ESC
je _QUIT
cmp ah, 48h ;UP
je _PLAYER.UP
cmp ah, 50h ;DOWN
je _PLAYER.DOWN
cmp ah, 4Bh ;LEFT
je _PLAYER.LEFT
cmp ah, 4Dh ;RIGHT
je _PLAYER.RIGHT
NoKeyAvailable:
ret
请注意:
您实际上并没有检查ZeroFlag来确定
AL
和AH
中的信息是否有效。数字1Bh(ESC)是ASCII码,必须从
AL
进行检查,但是其他所有代码48h(UP),50h(DOWN),4Bh(LEFT)和4Dh(RIGHT)都是扫描代码,因此必须从AH
检查。