I took x86 assembly as a hobby this past january so I could make games that would work on old 8086-powered computers like the PCj and Tandy 1000, but the books I found don't exactly teach much on that specific topic. While some dos and bios interrupts kind of do the job, they're far from perfect.
My main issue is reading the keyboard status for pressed keys without halting the program. I found a few methods, but they're very limited. INT 21h, AH 0Ch reads the last pressed key, but in a text-edition fashion. Not only does it read only one key at a time, but the notepad-like hit detection makes it impossible to know how long the key has been held. I've also seen references to the ports 60h to 64h during my Google travels, but it's just that, references. Actual explanations and working code is virtually non-existent. Or maybe I'm just that bad at using search engines.
What I need to know is whether a key is held down or not. The best solution would be to have a buffer/array of all the keyboard keys and read its state; 1 means it's down, 0 means it's not. Or just having access to a list of the last keys to have been hit and released would be nice (with a way to clear that buffer, of course). Can anyone point me in the right direction?
Edit: First off, I should have mentioned that I use Borland TASM. Now I compiled your code and it works great and all, even though I'm almost shy to admit I don't understand half of it. I tried to make it compatible with TASM but all it does is create garbage on the screen and freeze.
Here's what I came up with;
.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
I'm not sure if I even coded the interrupt right. And heck if I know how the ports 060h - 064h work.