如何检查在x86汇编键状态? [英] How to check keys status in x86 assembly?
问题描述
我把x86汇编作为一种业余爱好今年一月,所以我可以做游戏,将在诸如PCJ和坦迪1000,但我发现不完全教多少上特定主题的书旧8086供电的计算机上运行。虽然一些DOS和BIOS中断样做的工作,他们完美很远。
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.
我的主要问题是阅读pressed键键盘状态不停止该程序。我发现了一些方法,但它们是非常有限的。 INT 21H,AH 0CH读取最后pressed键,但在一个文本版时尚。它不仅读取一次只有一个按键,但记事本般的碰撞检测就不可能知道过了多久密钥已经举行。我也看到到端口60H引用在我的谷歌传播到64H,但它只是,引用。实际的解释和工作code是几乎不存在。或者,也许我只是不善于使用搜索引擎。
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.
我需要知道的是一键是否被按住或没有。最好的解决办法是让所有键盘按键的缓冲/阵列并读取其状态; 1意味着它的下跌,0表示事实并非如此。或者只是有机会获得最后一个键列表已经被击中并发布将是很好(有办法明确,当然缓冲区)。任何人都可以点我在正确的方向?
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?
编辑:首先,我应该提到,我使用Borland的TASM。现在我编译你的code和它的伟大工程和所有,即使我几乎羞于承认,我不明白它的一半。我试图使其与TASM兼容,但它是所有在屏幕上创建垃圾和冻结。
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.
这就是我想出了;
.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
我不知道如果我甚至codeD中断权利。而赫克,如果我知道如何端口060h的单元 - 064h工作
I'm not sure if I even coded the interrupt right. And heck if I know how the ports 060h - 064h work.
推荐答案
下面是你如何能做到这一点:
Here's how you can do it:
; 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, "$"
在DOS
运行它/ Win9x的/ NT / 2K / XP / 32位Vista / 7或DOSBox中。
Run it in DOS/Win9x/NT/2K/XP/32-bit Vista/7 or 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
这篇关于如何检查在x86汇编键状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!