Die*_*Jay 7 keyboard x86 assembly input x86-16
我在今年1月份将x86程序集作为业余爱好,因此我可以制作适用于旧PC 80和Tandy 1000等老式8086计算机的游戏,但我找到的书并没有完全讲授这个特定主题.虽然有些dos和bios中断了这项工作,但它们远非完美.
我的主要问题是在不停止程序的情况下读取按键的键盘状态.我发现了一些方法,但它们非常有限.INT 21h,AH 0Ch读取最后按下的键,但采用文本编辑方式.它不仅一次只能读取一个键,而且类似记事本的命中检测使得无法知道密钥被保持了多长时间.在Google旅行期间,我也看到了60h到64h端口的引用,但就是这样,引用.实际解释和工作代码几乎不存在.或者也许我只是在使用搜索引擎时那么糟糕.
我需要知道的是密钥是否被按下.最好的解决方案是拥有所有键盘键的缓冲区/数组并读取其状态; 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
Run Code Online (Sandbox Code Playgroud)
我不确定我是否正确编码了中断.如果我知道端口060h - 064h是如何工作的话.
您可以这样做:
; compile with NASM: nasm.exe -f bin kbd.asm -o kbd.com
bits 16
org 0x100
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]
mov word [es:9*4], irq1isr
mov [es:9*4+2],cs
sti
call test
cli ; update ISR address w/ ints disabled
pop word [es:9*4] ; restore ISR address
pop word [es:9*4+2]
sti
ret
test:
mov ah, 9
mov dx, msg1
int 0x21 ; 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)
mov dx, msg2
int 0x21 ; 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)
mov dx, msg3 ; print "ESC released"
int 0x21
ret
irq1isr:
pusha
; read keyboard scan code
in al, 0x60
; update keyboard state
xor bh, bh
mov bl, al
and bl, 0x7F ; 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, 0x61
mov ah, al
or al, 0x80
out 0x61, al
mov al, ah
out 0x61, al
; send EOI to master PIC
mov al, 0x20
out 0x20, al
popa
iret
kbdbuf:
times 128 db 0
msg1 db "Press and hold ESC", 13, 10, "$"
msg2 db "ESC pressed, release ESC", 13, 10, "$"
msg3 db "ESC released", 13, 10, "$"
Run Code Online (Sandbox Code Playgroud)
在 DOS/Win9x/NT/2K/XP/32 位 Vista/7 或 DosBox 中运行。
更新: TASM 版本:
; file: kbdt.asm
; compile with TASM/TLINK:
; tasm.exe kbdt.asm
; tlink.exe /t kbdt.obj
.286
code segment use16
assume cs:code, ds:code, ss:code
org 100h
main:
xor ax, ax
mov es, ax
cli ; update ISR address w/ ints disabled
push word ptr es:[9*4+2] ; preserve ISR address
push word ptr es:[9*4]
mov word ptr es:[9*4], offset irq1isr
mov es:[9*4+2],cs
sti
call test0
cli ; update ISR address w/ ints disabled
pop word ptr es:[9*4] ; restore ISR address
pop word ptr es:[9*4+2]
sti
ret
test0:
mov ah, 9
mov dx, offset msg1
int 21h ; 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)
mov dx, offset msg2
int 21h ; 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)
mov dx, offset msg3 ; print "ESC released"
int 21h
ret
irq1isr:
pusha
; read keyboard scan code
in al, 60h
; update keyboard state
xor bh, bh
mov bl, al
and bl, 7Fh ; 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, 61h
mov ah, al
or al, 80h
out 61h, al
mov al, ah
out 61h, al
; send EOI to master PIC
mov al, 20h
out 20h, al
popa
iret
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 ends
end main
Run Code Online (Sandbox Code Playgroud)