【问题标题】:The controls of my game freeze after the first keypress with int 16h / ah=1第一次按键 int 16h / ah=1 后,我的游戏控件冻结
【发布时间】:2019-09-19 11:29:52
【问题描述】:

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

【问题讨论】:

    标签: assembly keyboard x86-16 bios


    【解决方案1】:

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

            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下面的东西)

    【讨论】:

      【解决方案2】:

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

      如果没有可用的键,它将通过设置 ZeroFlag (ZF) 来通知您键盘键的可用性,或者如果键正在等待,则通过清除 ZeroFlag 来通知您键盘键的可用性。在后一种情况下,您还将收到按键的 ASCII 码和扫描码。
      重要的是,报告可用的按键保留在键盘缓冲区中。您在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 进行检查。

      【讨论】:

      • 谢谢!现在我可以控制我的播放器了。
      • @JulianStanev 如果你认为我的回答解决了你的编码问题,也许你可以考虑接受这个答案,这样每个人都知道这个问题不需要额外的关注。
      猜你喜欢
      • 1970-01-01
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 2018-05-27
      • 2018-03-30
      • 2013-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多