Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 8086汇编程序,INT 16,2_Assembly_X86 16 - Fatal编程技术网

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