我在今年1月份将x86程序集作为业余爱好,因此我可以制作适用于旧PC 80和Tandy 1000等老式8086计算机的游戏,但我找到的书并没有完全讲授这个特定主题 . 虽然有些dos和bios中断了这项工作,但它们远非完美 .
我的主要问题是在不停止程序的情况下读取按键的键盘状态 . 我发现了一些方法,但它们非常有限 . INT 21h,AH 0Ch读取最后按下的键,但采用文本编辑方式 . 它不仅一次只能读取一个键,而且类似记事本的命中检测使得无法知道密钥被保持了多长时间 . 在Google旅行期间,我也看到了60h到64h端口的引用,但就是这样,引用 . 实际解释和工作代码几乎不存在 . 或者也许我只是在使用搜索引擎时那么糟糕 .
我需要知道的是密钥是否被按下 . 最好的解决方案是拥有所有键盘键的缓冲区/数组并读取其状态; 1表示它已经下降,0表示它不是 . 或者只是访问已被命中和释放的最后一个键的列表将是很好的(当然,有一种方法可以清除缓冲区) . 谁能指出我正确的方向?
Edit: 首先,我应该提到我使用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
我不确定我是否正确编码了中断 . 如果我知道端口060h - 064h是如何工作的话 .
3 回答
这是你如何做到的:
在DOS / Win9x / NT / 2K / XP / 32位Vista / 7或DosBox中运行它 .
UPDATE: TASM版本:
通常对于像这样的旧系统,人们使用BIOS有点像预先提供的库函数集,其中键盘函数之类的东西仅在它们方便时使用 . 在您的情况下,BIOS键盘服务不方便,因此您不使用它们 .
相反,您希望用您自己的键盘中断处理程序替换BIOS键盘中断处理程序并实现您自己的键盘驱动程序 . 键盘使用IRQ1,它是中断9.中断向量表从0x0000:0x0000开始,所以你想得到4个字节在0x0000:9 * 4 = 0x0000:0x0024并将它们存储在某处(所以你可以把东西放回去当你的软件退出时正常)并将你自己的键盘IRQ处理程序的地址(偏移然后段)放在那里 .
要编写自己的键盘驱动程序,首先要了解所涉及的硬件有两个 . 计算机中有键盘控制器芯片(或“PS / 2控制器”),它与键盘内部的芯片通话(通过串行通信) .
有关键盘控制器芯片的信息,请参阅http://wiki.osdev.org/%228042%22_PS/2_Controller
有关键盘内部芯片的信息,请参阅http://wiki.osdev.org/PS/2_Keyboard
使用端口60h和端口64h轮询键盘的示例: