Tomé x86 asamblea como hobby el pasado enero para poder hacer juegos que funcionaran en computadoras antiguas con 8086 como PCj y Tandy 1000, pero los libros que encontré no enseñan exactamente mucho sobre ese tema específico. Aunque algunas interrupciones de dos y biografías hacen el trabajo, están lejos de ser perfectas.¿Cómo verificar el estado de las teclas en el ensamblaje x86?
Mi problema principal es leer el estado del teclado para las teclas presionadas sin detener el programa. Encontré algunos métodos, pero son muy limitados. INT 21h, AH 0Ch lee la última tecla presionada, pero en una edición de texto. No solo lee solo una clave a la vez, sino que la detección de impacto similar a un bloc de notas hace que no se sepa cuánto tiempo se mantuvo presionada la tecla. También he visto referencias a los puertos de 60h a 64h durante mis viajes a Google, pero es solo eso, referencias. Las explicaciones reales y el código de trabajo son prácticamente inexistentes. O tal vez soy tan malo en el uso de los motores de búsqueda.
Lo que necesito saber es si una tecla está presionada o no. La mejor solución sería tener un buffer/matriz de todas las teclas del teclado y leer su estado; 1 significa que está abajo, 0 significa que no. O simplemente tener acceso a una lista de las últimas claves para haber sido golpeado y liberado sería bueno (con una forma de borrar ese buffer, por supuesto). ¿Alguien puede señalarme en la dirección correcta?
Edit: En primer lugar, debería haber mencionado que utilizo Borland TASM. Ahora compilé tu código y funciona muy bien y todo, a pesar de que soy casi tímido para admitir que no entiendo ni la mitad. Traté de hacerlo compatible con TASM, pero todo lo que hace es crear basura en la pantalla y congelar.
Esto es lo que se me ocurrió;
.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
No estoy seguro si incluso codifiqué la interrupción correcta. Y diablos si sé cómo funcionan los puertos 060h - 064h.
Su principal problema es que usted está haciendo un programa mientras .EXE se supone que el código se compila en un programa .COM. Ver la respuesta actualizada. –
Tetris OS de trabajo que hace lo que quiere: https://github.com/programble/tetrasm –