Ho preso l'assemblaggio x86 come passatempo il prossimo gennaio, così ho potuto creare giochi che funzionassero su vecchi computer con tecnologia 8086 come PCj e Tandy 1000, ma i libri che ho trovato non insegnano esattamente molto su quell'argomento specifico. Mentre alcuni dos e bios interrompono il lavoro, sono tutt'altro che perfetti.Come verificare lo stato delle chiavi nell'assemblaggio x86?
Il mio problema principale è la lettura dello stato della tastiera per i tasti premuti senza interrompere il programma. Ho trovato alcuni metodi, ma sono molto limitati. INT 21h, AH 0Ch legge l'ultimo tasto premuto, ma in modo testo-edizione. Non solo legge solo una chiave alla volta, ma la rilevazione del colpo simile a un blocco note rende impossibile sapere per quanto tempo il tasto è stato trattenuto. Ho visto anche riferimenti alle porte da 60h a 64h durante i miei viaggi su Google, ma è solo questo, riferimenti. Le spiegazioni effettive e il codice di lavoro sono praticamente inesistenti. O forse sono così male nell'usare i motori di ricerca.
Quello che devo sapere è se un tasto è premuto o meno. La soluzione migliore sarebbe avere un buffer/array di tutti i tasti della tastiera e leggere il suo stato; 1 significa che è inattivo, 0 significa che non lo è. O semplicemente avere accesso a un elenco delle ultime chiavi che sono state colpite e rilasciate sarebbe bello (con un modo per cancellare quel buffer, ovviamente). Qualcuno può indicarmi la giusta direzione?
Modifica: Prima di tutto, avrei dovuto dire che uso Borland TASM. Ora ho compilato il tuo codice e funziona alla grande e tutto, anche se sono quasi timido ad ammettere che non ne capisco la metà. Ho provato a renderlo compatibile con TASM, ma tutto ciò che fa è creare immondizia sullo schermo e congelare.
Ecco cosa mi è venuto in mente;
.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
Non sono sicuro di aver anche corretto l'interrupt. E diamine se so come funzionano le porte 060h - 064h.
Il tuo problema principale è che si sta facendo un programma eseguibile, mentre il codice dovrebbe essere compilato in un programma .COM. Vedi la risposta aggiornata. –
Sistema operativo Tetris funzionante che fa ciò che vuoi: https://github.com/programble/tetrasm –