Как проверить состояние ключей в сборке x86?

В январе этого года я увлекся ассемблированием x86, чтобы создавать игры, которые будут работать на старых компьютерах с процессором 8086, таких как PCj и Tandy 1000, но книги, которые я нашел, мало что говорят по этой конкретной теме. Хотя некоторые прерывания dos и bios выполняют свою работу, они далеки от совершенства.

Моя основная проблема заключается в чтении состояния клавиатуры для нажатых клавиш без остановки программы. Я нашел несколько методов, но они очень ограничены. INT 21h, AH 0Ch считывает последнюю нажатую клавишу, но в текстовом виде. Мало того, что он считывает только одну клавишу за раз, но обнаружение нажатия, похожее на блокнот, делает невозможным определение того, как долго клавиша была нажата. Я также видел ссылки на порты с 60h по 64h во время моих путешествий по Google, но это всего лишь ссылки. Фактических объяснений и рабочего кода практически не существует. Или, может быть, я просто так плохо пользуюсь поисковыми системами.

Мне нужно знать, нажата ли клавиша или нет. Лучшим решением было бы иметь буфер/массив всех клавиш клавиатуры и читать его состояние; 1 означает, что он не работает, 0 означает, что нет. Или просто иметь доступ к списку последних нажатых и отпущенных клавиш (конечно, с возможностью очистки этого буфера). Может кто-то указать мне верное направление?

Изменить:Во-первых, я должен был упомянуть, что использую Borland TASM.Теперь я скомпилировал ваш код, и он отлично работает и все такое, хотя я почти стесняюсь признаться, что не понимаю и половины его. Я пытался сделать его совместимым с TASM, но все, что он делает, это создает мусор на экране и зависает.

Вот что я придумал;

.MODEL TINY
.STACK 256

.DATA
kbdbuf DB 128 DUP (0)

msg1 db "Press and hold ESC", 13, 10, "$"
msg2 db "ESC pressed, release ESC", 13, 10, "$"
msg3 db "ESC released", 13, 10, "$"

.CODE
main PROC
    org 0100h
    mov ax, @data
    mov ds, ax

    xor     ax, ax
    mov     es, ax

    cli                         ; update ISR address w/ ints disabled
    push    word [es:9*4+2]     ; preserve ISR address
    push    word [es:9*4]
    lea si, irq1isr
    mov     word [es:9*4], si   ; requires a register
    mov     [es:9*4+2],cs
    sti

        mov     ah, 9
        lea     dx, msg1
        int     021h                ; print "Press and hold ESC"

    test1:
        mov     al, [kbdbuf + 1]    ; check Escape key state (Esc scan code = 1)
        or      al, al
        jz      test1               ; wait until it's nonzero (pressed/held)

        lea     dx, msg2
        int     021h                ; print "ESC pressed, release ESC"

    test2:
        mov     al, [kbdbuf + 1]    ; check Escape key state (Esc scan code = 1)
        or      al, al
        jnz     test2               ; wait until it's zero (released/not pressed)

        lea     dx, msg3            ; print "ESC released"
        int     021h

    cli                         ; update ISR address w/ ints disabled
    pop     word [es:9*4]       ; restore ISR address
    pop     word [es:9*4+2]
    sti

    ret

    irq1isr:
    push    ax bx

    ; read keyboard scan code
    in      al, 060h

    ; update keyboard state
    xor     bh, bh
    mov     bl, al
    and     bl, 07Fh            ; bx = scan code
    shr     al, 7               ; al = 0 if pressed, 1 if released
    xor     al, 1               ; al = 1 if pressed, 0 if released
    mov     [cs:bx+kbdbuf], al

    ; send EOI to XT keyboard
    in      al, 061h
    mov     ah, al
    or      al, 080h
    out     061h, al
    mov     al, ah
    out     061h, al

    ; send EOI to master PIC
    mov     al, 020h
    out     020h, al

    pop     bx ax
    iret
main ENDP

END main

Я не уверен, правильно ли я закодировал прерывание. И черт возьми, если я знаю, как работают порты 060h - 064h.

7
задан DieJay 10 May 2012 в 19:07
поделиться