第一次使用 int 16h / ah=1 按键后,我的游戏控件冻结

The controls of my game freeze after the first keypress with int 16h / ah=1

我正在用程序集 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

您正在使用 int 16h,1。 如你所见here,特殊键(如箭头)有一个名为扫描码的值,扫描码在啊中返回。尝试

        mov ah,01h
        int 16h
        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

如果那不行,我建议你调试并检查问题是否出在其他地方(例如尝试在 _PLAYER.UP 下打印一些东西)

您的 _KEYCHECK 函数正在使用 BIOS.ReadKeyboardStatus 函数。

如果没有键可用,它会通过设置 ZeroFlag (ZF) 通知您键盘键的可用性,或者如果键正在等待,则通过清除 ZeroFlag 来通知您键盘键的可用性。在后一种情况下,您还将收到密钥的 ASCII 码和扫描码。
这里重要的是报告可用的键保留在键盘缓冲区中。您在 ALAH 中获得的信息只是预览而不是实际密钥(在某种意义上)。这解释了您的观察结果:

... but if any other key was pressed before that the controls frees ...

解决办法是从键盘缓冲区中删除键。这就是 BIOS.ReadKeyboardCharacter 所做的。如果一个键正在等待,它会很快 return 并从缓冲区中删除该键。如果没有可用的密钥,它将等到一个可用,然后 return 从缓冲区中删除该密钥。

_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.
  • 进行检查