我正在用程序集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。
这里重要的是,报告的可用键保留在键盘缓冲区中。在ALAH中获得的信息只是预览,而不是实际的键(在某种意义上)。这解释了您的观察:


...但是如果在此之前按下了其他任何键,则控件将释放...


解决方案是从键盘缓冲区中删除键。这就是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来确定ALAH中的信息是否有效。
数字1Bh(ESC)是ASCII码,必须从AL进行检查,但是其他所有代码48h(UP),50h(DOWN),4Bh(LEFT)和4Dh(RIGHT)都是扫描代码,因此必须从AH检查。

08-15 22:27