В январе этого года я увлекся ассемблированием 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.