Элементы управления моей игры зависают после первого нажатия клавиши с int 16h / ah = 1 - PullRequest
3 голосов
/ 30 апреля 2019

Я кодирую игру в сборке 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

Ответы [ 2 ]

3 голосов
/ 01 мая 2019

Ваша функция _KEYCHECK использует BIOS.ReadKeyboard Состояние Функция.

Он будет информировать вас о наличии клавиши клавиатуры, установив ZeroFlag (ZF), если клавиша недоступна, или очистив ZeroFlag, если клавиша ожидает. В последнем случае вы также получите код ключа ASCII и код сканирования.
Здесь важно то, что сообщаемая клавиша остается в буфере клавиатуры . Информация, которую вы получаете в AL и AH - это просто предварительный просмотр, а не фактический ключ (в некотором смысле). Это объясняет ваше наблюдение:

... но если до этого была нажата какая-либо другая клавиша, органы управления освобождаются ...

Решение состоит в том, чтобы удалить ключ из буфера клавиатуры. Вот что делает BIOS.ReadKeyboard Символ . Если ключ ожидает, он очень быстро вернется, удалив ключ из буфера. Если ключ недоступен, он будет ждать, пока он не появится, а затем вернется, удалив этот ключ из буфера.

_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.
1 голос
/ 01 мая 2019

Вы используете int 16h, 1. Как вы можете видеть здесь , специальные клавиши (например, стрелки) имеют значение, называемое кодом сканирования, и код сканирования возвращается в ах. Попробуйте

        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)

...