在你的主循环中,你检查是否有击键可用。BIOS有CheckKeystroke function 01h用于此。如果它返回零标志集(ZF=1)则没有键等待,你可以继续循环。但是如果零标志被清除(ZF=0),则密钥(至少一个)正在BIOS维护的键盘缓冲区中等待。您必须从缓冲区中删除这个键。如果您没有删除,缓冲区将迅速填充到其最大15个键,您可能会失去对程序的控制。BIOS具有GetKeystroke function 00h以从缓冲区中获取最旧的键,在AL寄存器中返回其ASCII码,在AH寄存器中返回其扫描码。(如果缓冲区为空,此函数将等待按键,但在我们的情况下,这不会发生,因为我们事先检查了按键的可用性)。 我们感兴趣的箭头键由AH寄存器中的扫描码标识:向上= 48 h,向左= 4 Bh,向右=4Dh,向下= 50 h。
使用修饰键
在主循环中,你向BIOS请求键盘标志。如果你不需要区分Left-Ctrl,Left-Alt,Right-Alt,Right-Ctrl键,那么你可以使用BIOS GetKeyboardFlags function 02h,它会在AL寄存器中返回以下项目:
76543210
.......1 Right shift key is depressed
......1. Left shift key is depressed
.....1.. Either ctrl key is depressed
....1... Either alt is depressed
...1.... Scroll lock is enabled
..1..... Num lock is enabled
.1...... Caps lock is enabled
1....... Insert key is enabled
76543210
.......1 Left ctrl key is depressed
......1. Left alt key is depressed
.....1.. Right ctrl key is depressed
....1... Right alt is depressed
...1.... Scroll lock is depressed
..1..... Num lock is depressed
.1...... Caps lock is depressed
1....... SysRq key is depressed (Acer reports Insert key)
ORG 256 ; Assembled with FASM
UseShifts = 0
UseArrows = 1
mov ax, 0003h ; BIOS.SetVideoMode 80x25 text
int 10h
mov dx, 1724h ; DX is position (36,23)
xor bx, bx
MainEx:
mov cx, bx ; CX is direction [-1=Left,0=Right]
Main:
call Delay
jcxz .Right
.Left:
cmp dl, 2 ; Left border
ja .Move
jmp .Turn
.Right:
cmp dl, 72 ; Right border
jb .Move
.Turn:
not cx ; -> CX is new direction
.Move:
call MovePaddle ; -> DX is new position
call MovePaddle ; -> DX is new position
IF UseShifts
mov ah, 02h ; BIOS.GetKeyboardFlags
int 16h ; -> AL
test al, 00000011b
jz .Neither
xor bx, bx
test al, 00000001b
jnz MainEx ; Set direction=0 on <RIGHT-SHIFT>
not bx
jmp MainEx ; Set direction=-1 on <LEFT-SHIFT>
.Neither:
END IF
mov ah, 01h ; BIOS.CheckKeystroke
int 16h ; -> AX ZF
jz Main ; No key available
mov ah, 00h ; BIOS.GetKeystroke
int 16h ; -> AX
IF UseArrows
xor bx, bx
cmp ah, 4Dh
je MainEx ; Set direction=0 on <RIGHT-ARROW>
not bx
cmp ah, 4Bh
je MainEx ; Set direction=-1 on <LEFT-ARROW>
END IF
cmp al, 27
jne Main ; Ignore all other keys except <ESC>
Exit:
int 20h ; DOS.TerminateProgram
; ----------------------
; IN () OUT ()
Delay:
push ds ax
xor ax, ax
mov ds, ax
mov ax, [046Ch] ; BIOS.TimerTick
.Again:
cmp ax, [046Ch]
je .Again ; TimerTick didn't change
pop ax ds
ret
; ----------------------
; IN (cx,dx) OUT (dx)
MovePaddle:
push ax bx cx
mov ax, 0001h ; Move right .. Wipe at +0, Draw at +1
jcxz .Wipe
mov ax, 05FAh ; Move left .. Wipe at +5, Draw at -6
.Wipe:
push ax ; (1)
add dl, ah ; AH is {0,5}
mov bx, 0007h ; BH is DisplayPage, BL is Attribute
mov ah, 02h ; BIOS.SetCursorPosition
int 10h
mov cx, 1 ; ReplicationCount (PaddleStep)
mov ax, 0920h ; BIOS.WriteCharacterAndAttribute, AL is Space
int 10h
.Draw:
pop ax ; (1)
add dl, al ; AL is {1,-6}
mov ah, 02h ; BIOS.SetCursorPosition
int 10h
mov cx, 6 ; ReplicationCount (PaddleLength)
mov bl, 0Eh ; BL is Attribute
mov ax, 09DCh ; BIOS.WriteCharacterAndAttribute, AL is HalfBlock
int 10h
pop cx bx ax
ret
; ----------------------
4条答案
按热度按时间gijlo24d1#
你确定你不想用箭头键来左右移动吗?control和shift的问题是它们不会“返回”一个键,而是修改另一个被按下的键。这是在键盘中断处理程序中处理的(9,国际红十字会),你可以“钩住”它。我想在“BIOS数据区”中查找会更容易并观察中断处理程序跟踪控制键和Shift键状态的位置。在我看来,BDA在40h段。键盘状态标志在... 17h和18h?不要相信我的话,因为这些偏移,查一下。拉尔夫·布朗的中断列表。这一切都假设“8086”的意思是,像...古董。:)
nwlqm0z12#
假设您只在BIOS下执行此操作,您可能会发现使用更高级别的BIOS键盘中断更容易-int 0x16 AH=0x01用于一般击键,int 0x16 AH=0x02用于ctrl/shift等。尽管存在许多其它可能性(包括其它INT 0x 16命令和如先前所建议的低级键盘int 0x 09和bios数据区。。我强烈支持Ralf Brown's Interrupt List的推荐-一个极好的资源!
w1e3prcc3#
Bios将键存储在一个16个字母的缓冲区中。这意味着如果一个os太慢,每当它读到下一个键击时,它就会从缓冲区中读取。
您可以使用int 16h并将ah设置为02h来将al设置为缓冲区中的下一个字符。但是,如果您要检查缓冲区的状态(是否有键),请查看this.,它基本上深入到ah 02h
既然你问的是箭头键,下面是它们的十六进制代码:
1.第0x19天
s6fujrry4#
控制移动的常用方法是使用键盘上的箭头键。Shift、Ctrl和Alt键通常用作操作键:想想射击、跳跃、使用小工具等动作。
使用箭头键
在你的主循环中,你检查是否有击键可用。BIOS有CheckKeystroke function 01h用于此。如果它返回零标志集(ZF=1)则没有键等待,你可以继续循环。但是如果零标志被清除(ZF=0),则密钥(至少一个)正在BIOS维护的键盘缓冲区中等待。您必须从缓冲区中删除这个键。如果您没有删除,缓冲区将迅速填充到其最大15个键,您可能会失去对程序的控制。BIOS具有GetKeystroke function 00h以从缓冲区中获取最旧的键,在AL寄存器中返回其ASCII码,在AH寄存器中返回其扫描码。(如果缓冲区为空,此函数将等待按键,但在我们的情况下,这不会发生,因为我们事先检查了按键的可用性)。
我们感兴趣的箭头键由AH寄存器中的扫描码标识:向上= 48 h,向左= 4 Bh,向右=4Dh,向下= 50 h。
使用修饰键
在主循环中,你向BIOS请求键盘标志。如果你不需要区分Left-Ctrl,Left-Alt,Right-Alt,Right-Ctrl键,那么你可以使用BIOS GetKeyboardFlags function 02h,它会在AL寄存器中返回以下项目:
如果您确实需要区分Left-Ctrl、Left-Alt、Right-Alt、Right-Ctrl键,则可以使用BIOS GetKeyboardFlags function 12h,该BIOS还在AH寄存器中返回以下项目:
包含的演示程序显示了一个浮在屏幕底部附近的桨从左到右来回移动。
如果启用了 UseArrows(非零),则按下左箭头或右箭头将更改焊盘的方向。
如果启用了 UseShifts(非零),则按下左移或右移将更改开关的方向。
您可以同时启用 UseArrows 和 * UseShift *。
按Esc键停止程序。