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

旧街凉风 提交于 2019-11-28 09:21:39

问题


I am coding a game in assembly 8086. I fixed the issue when the game didn't open, but I can't fix the controls.

The ESC key works. When I press it, it goes to _QUIT function, but if any other key was pressed before that, the controls freeze and don't react on any key.

Is there something wrong with my function?

I tried to change the AL register to AH, but it didn't work.

_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

回答1:


Your _KEYCHECK function is using the BIOS.ReadKeyboardStatus function.

It will inform you about the availability of a keyboard key by setting the ZeroFlag (ZF) if no key is available, or by clearing the ZeroFlag if a key is waiting. In the latter case you will also receive the key's ASCII code and scancode.
The important thing here is that a key that is reported available stays in the keyboard buffer. The info that you get in AL and AH is just a preview not the actual key (in a sense). This explains your observation:

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

The solution is to remove the key from the keyboard buffer. That's what BIOS.ReadKeyboardCharacter does. If a key is waiting it will return very quickly with the key removed from the buffer. If no key is available it will wait until one comes available and then return with that key removed from the buffer.

_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

Please note:

  • You didn't actually inspect the ZeroFlag to find out if the info in AL and AH was valid.
  • The number 1Bh (ESC) is an ASCII code and has to be checked from AL but all the other codes 48h (UP), 50h (DOWN), 4Bh (LEFT), and 4Dh (RIGHT) are scancodes and thus have to be checked from AH.



回答2:


You are using int 16h,1. As you can see here, special keys(like arrows) has a value called scan code and the scan code is returned in ah. Try

        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

If thats not working, I suggest you to debug and check if the problem not in another place(For example try to print something under _PLAYER.UP)



来源:https://stackoverflow.com/questions/55927095/the-controls-of-my-game-freeze-after-the-first-keypress-with-int-16h-ah-1

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!