tags:

views:

460

answers:

3

Hi,I got stuck at this thing,I want to see if right shift button has been pressed,so I have this assambler code:

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

why is it not working ?,I think the problem is that int 16,2 is not working properly,if so why is that? here is what INT 16,2 is supposed to do:

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

I never see the message,I've looked at the AL register in debug and it doesn't seem to change after I call INT 16,2.I'm running Win 7 on a x86 arhitecture,and I'm working with tasm

A: 

I cannot explain why your code isn't working, but you can replace

mov ah,10000000b
shl al,7 
and al,10000000b
cmp al,ah         ;check if first bit is 1

by

test al, 1

which does the same thing and is more idiomatic, if there is such a thing as an idiom in assembly.

EDIT: As Michael points out in the comment below, you need to reverse the conditional jump if you use the test instruction. test al, C sets ZF if and only the bitwise and of al AND C is zero.

Pascal Cuoq
As Ruben's answer indirectly hints at, you need a jnz instead of a je if you're using the test instruction (ZF=1 if any bits in the mask matches, and je tests for ZF=0).
Michael Madsen
Now you've got me confused. I think that you're right that it's necessary to reverse the conditional jump, but I think that the parenthesis part of your comment is all backwards. ZF=1 if none of the bits matches, and `je` tests for ZF=1, right?
Pascal Cuoq
Er, right, of course - my bad, that's what happens when you stay up too late after a long day.
Michael Madsen
+1  A: 

you should be able to clean up your check by doing :

test al,1
jnz rshift
Ruben Bartelink
shouln't I still shift the bits in al ?
John Retallack
I got it,how about if I want to check the second bit,then I need to shift right by one bit,am i right ?
John Retallack
@John No, use `test al, 2` in this case.
Pascal Cuoq
Ruben Bartelink
@Pascal: You meant to say 10b instead of 2 didnt you :P
Ruben Bartelink
2 in decimal is 10b
John Retallack
@John: you could do `shr al,1` and then `test al,1` as you suggest, but you wouldnt (as Pascal said). You only shift if you need it to be in that position. e.g. if you wanted to save the result somewhere as a boolean value or you wanted to OR the bit into something else in a specific position. In all other cases, to test a bit, you just mask with it and then check if that yielded zero or non-zero
Ruben Bartelink
@John: I know 2 in decimal is 10b, but the point is when explaining bit masks, its much easier giving examples in binary for clarity
Ruben Bartelink
thanks for the examples,I got it,still that doesn't solve my problem
John Retallack
The interrupt code and the test look fine. If you want to edit in your final code at the end of your post someone may see the problem... In what sense is it not working? Do you ever see the message? Do you always see the message? You are aware you need to be pressing the key as the program starts etc.?
Ruben Bartelink
"You are aware you need to be pressing the key as the program starts",Yes,before I read the shift state I read a character from the keyboard
John Retallack
Sounds like you're fine on that then. Just to double check... and you're aware that it's current live async state, as opposed to e.g. the magic of the ModifierKeys in .NET, as described at http://www.arl.wustl.edu/~lockwood/class/ece291/books/CH13/CH13-3.html#HEADING3-131
Ruben Bartelink
In the link you gave me it says that I have to flush the type ahead buffer,how do I do that ?
John Retallack
Repeatedly read input until there isnt any. There's a int 21h service to check if there is any and probably a 16h (which would be better). Main point is that this call isnt telling you whether someone had the shift key down when they pressed a key, its whether its down at the very instant of your interrupt.
Ruben Bartelink
A: 

How are you testing this?

Out of curiosity, i made a simple program (code below). When run under Windows console, it detects left shift (Result: 2) but never detects right shift (expected Result: 1, but only got Result: 0).

When run under pure DOS (in VMWare), it correctly displays all combinations (0 to 3).

So it seems to be an artifact of NTVDM (Windows DOS emulation), though I don't have any sources to cite.

My code:

.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
atzz
How is this supposed to work ?Do I have to press shift before running the program,I've tested it and is always displays result zero.I'm running Win 7 x86,and I've tested it with tasm
John Retallack
atzz
atzz