gpt4 book ai didi

assembly - 如何检查 x86 程序集中的 key 状态?

转载 作者:行者123 更新时间:2023-12-04 12:42:35 27 4
gpt4 key购买 nike

去年 1 月,我把 x86 汇编作为一种爱好,这样我就可以制作可以在 PCj 和 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

我不确定我是否对中断进行了正确编码。哎呀,如果我知道端口 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, "$"

在 DOS/Win9x/NT/2K/XP/32-bit 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

关于assembly - 如何检查 x86 程序集中的 key 状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10524855/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com