Assembly 8086汇编程序,INT 16,2
我被这东西卡住了,我想看看右换档按钮是否被按下,所以我有这个密码:Assembly 8086汇编程序,INT 16,2,assembly,x86-16,Assembly,X86 16,我被这东西卡住了,我想看看右换档按钮是否被按下,所以我有这个密码: mov ah,2 int 16h ;calling INT 16,2 - Read Keyboard Flags interrupt mov ah,10000000b shl al,7 and al,10000000b cmp al,ah ;check if first bit is 1 je rshift jmp final rshift: mov ah,9 lea dx
mov ah,2
int 16h ;calling INT 16,2 - Read Keyboard Flags interrupt
mov ah,10000000b
shl al,7
and al,10000000b
cmp al,ah ;check if first bit is 1
je rshift
jmp final
rshift:
mov ah,9
lea dx,rsh ;rsh is a string that says that "right shift button has been pressed"
int 21h
jmp final
final: ; quit program
mov ax,4c00h
int 21h
为什么它不工作?我认为问题是int 16,2工作不正常,如果是,为什么?
以下是INT 16,2应该做的事情:
AH = 02
on return:
AL = BIOS keyboard flags (located in BIOS Data Area 40:17)
|7|6|5|4|3|2|1|0| AL or BIOS Data Area 40:17
| | | | | | | `---- right shift key depressed
| | | | | | `----- left shift key depressed
| | | | | `------ CTRL key depressed
| | | | `------- ALT key depressed
| | | `-------- scroll-lock is active
| | `--------- num-lock is active
| `---------- caps-lock is active
`----------- insert is active
我从来没有看到过这条消息,我在调试中查看了AL寄存器,在调用INT 16,2后,它似乎没有改变。我在x86体系结构上运行Win 7,我在使用tasm,我无法解释为什么您的代码不工作,但您可以替换它
mov ah,10000000b
shl al,7
and al,10000000b
cmp al,ah ;check if first bit is 1
借
如果在汇编中有一个习语这样的东西,那么哪个做同样的事情,并且更习惯用法
编辑:
正如Michael在下面的评论中指出的,如果使用
test
指令,则需要反转条件跳转<当且仅当al
和C
的位and为零时,code>test al,C设置ZF。您应该能够通过执行以下操作来清理支票:
test al,1
jnz rshift
你是如何测试这个的 出于好奇,我做了一个简单的程序(代码如下)。在Windows控制台下运行时,它检测到左移(
Result:2
),但从未检测到右移(预期的Result:1
,但仅获得Result:0
)
在纯DOS(在VMWare中)下运行时,它会正确显示所有组合(0到3)
因此,它似乎是NTVDM(Windows DOS仿真)的产物,尽管我没有任何来源可供引用
我的代码:
.model small
.code
start:
mov ax, seg msg
mov ds, ax
mov ah, 2
int 16h
and al,3 ; get two lower bits - both SHIFTs
add digit, al ; convert to decimal
lea dx, msg
mov ah, 9
int 21h
mov ax, 4c00h
int 21h
.data
msg db 'Result: '
digit db '0'
db 13,10,'$',0
.stack
db 16384 dup(?)
end start
我还应该移位al中的位吗?我知道了,如果我想检查第二位,那么我需要右移一位,对吗?@John No,在这种情况下使用
test al,2
。没有理由移位,传递给test的值充当and掩码,这实际上意味着只检查位0。这有点像在C中说if(flag&1)==1,而不是说(flag&1)!=0
,也就是说,你用某种东西来屏蔽它,你要看位是否“显示”在屏蔽中,而不是担心哪个位显示出来(如果屏蔽中只有一个位,那么只能有一个位)。希望这能解释。@Pascal:你的意思是说10b而不是2,不是吗:PAs Ruben的回答间接暗示,如果你使用测试指令,你需要一个jnz而不是je(如果掩码中有匹配的位,则ZF=1,je测试ZF=0)。现在你把我弄糊涂了。我认为你是对的,有必要反转条件跳转,但我认为你评论中的括号部分完全是反向的。ZF=1如果没有匹配的位,并且je
测试ZF=1,对吗?呃,对,当然-我的错,当你在漫长的一天之后熬夜太晚时会发生这种情况。这应该如何工作?我是否必须在运行程序之前按shift键,我已经测试过,并且总是显示结果0。我正在运行Win 7 x86,我已经用Tasmeyes测试过了,您必须事先按下shift键,因为代码中没有延迟(尽管添加延迟或将代码包装成循环并不困难)。在Windows下,您也可以这样做:ping-n5 localhost&&test.exe
(假设test.exe是上面的程序),并有5秒钟的时间按下(并保持)所需的键。我开始考虑循环。。。在Windows命令行中运行以下命令,您将能够“交互地”观察结果的变化:)对于(11万)do(ping-n2 localhost>nul&test.exe)中的/L%I(很抱歉,我现在附近没有Windows,因此上面的行未经测试)
.model small
.code
start:
mov ax, seg msg
mov ds, ax
mov ah, 2
int 16h
and al,3 ; get two lower bits - both SHIFTs
add digit, al ; convert to decimal
lea dx, msg
mov ah, 9
int 21h
mov ax, 4c00h
int 21h
.data
msg db 'Result: '
digit db '0'
db 13,10,'$',0
.stack
db 16384 dup(?)
end start