Reading Ctrl, Alt and Shifts....

25 views
Skip to first unread message

Tripharn

unread,
Sep 5, 2002, 10:51:49 PM9/5/02
to
Last question I promise :)
I require to read the shift, control and alt keys....when they are pressed,
or released.
I also have to know if a letter is pressed or released.
I am currently using...

MOV AH, 01H
INT 16H

And I can read all the letters etc, but then I can't read any shift status??
Is that correct?

If I use

MOV AH, 02H
INT 16H

Then I can read the shift status but not the other keys....is there a way to
do both in one go???


Frank Kotler

unread,
Sep 6, 2002, 12:20:49 AM9/6/02
to
Tripharn wrote:

> Last question I promise :)

I hope not! No further questions is usually a sign that you're dead :)

> I require to read the shift, control and alt keys....when they are pressed,
> or released.
> I also have to know if a letter is pressed or released.
> I am currently using...
>
> MOV AH, 01H
> INT 16H
>
> And I can read all the letters etc,

Strictly speaking, this is the XT varient, and there are a few exotic
keystrokes it *won't* read - ctrl-down-arrow is one, I think...
(discovered it making a "draw" program, IIRC) Using ah=11h - the AT
varient will pick it up. I wouldn't bother...

> but then I can't read any shift status??
> Is that correct?
>
> If I use
>
> MOV AH, 02H
> INT 16H
>
> Then I can read the shift status but not the other keys....is there a way to
> do both in one go???

I don't think I know a way - they're kinda separate issues... As well as
doing it with int 16h, you can read the keyboard status flags from the
bios data area at segment 40h - 0040:0017 and "extended" flags at
0040:0018 (unless you're running an XT - if we're going to think about
that kind of thing, we ought to check for a mono monitor - which my
example doesn't). This isn't exactly what you want, but it displays the
keyboard status flags "live" so you can watch what happens as you press
and release left|right shift|alt|ctrl and the caps-lock, num-lock, and
scroll-lock keys. It's the same info as returned by int 16h/2, AFAIK.
Shows another way to display binary, too. Nasm syntax, if you're using
something else you'll have to touch it up a little...

Best,
Frank


;----------------------------------
; shows keyboard status flags
;
; nasm -f bin -o bda01.com bda01.asm
;-----------------------------------

org 100h

section .text

; make screen memory our destination
mov ax, 0B800h ; blindly assume vga
mov es, ax
xor di, di

; clear the screen
mov cx, 80 * 25
xor ax, ax
rep stosw

; make Bios Data Area our source
mov ax, 40h
mov ds, ax

top:
mov bx, [17h] ; keyboard status flags 0040:0017
mov di, (80 * 12 + 32) * 2 ; middle of screen

; display bx as binary
mov cx, 16 ; sixteen bits
show:
mov ax, 700h ; al = 0, ah = color
rcl bx, 1 ; get a bit into carry-flag
adc al, '0' ; make al '0' or '1'
stosw ; write character and color
loop show

mov ah, 1 ; any key pressed?
int 16h
jz top
xor ah, ah ; get the key
int 16h
cmp al, 1Bh ; was it ESC?
jnz top
; quit
mov ah, 4Ch
int 21h
;---------------------


Tripharn

unread,
Sep 6, 2002, 2:55:40 AM9/6/02
to
I'm confused, how can AH=01H read a combination of CTRL-A, but not CTRL by
itself??

Since I'm new to assembly, how do I read the Keyboard status flags? So far
I've got a program that reads the input from the keyboard, and displays the
make / break codes to the screen. I also at the same time have to show if
the shift, ctrl or alt is being pressed by displaying its binary value in
the top right of the screen.

I've almost completed except for getting the program to even register if the
shift keys etc are being pressed. So reading the status flags would be
simple, if I knew how.....

Tripharn

"Frank Kotler" <fbko...@attbi.com> wrote in message
news:3D782C02...@attbi.com...

Ross Simpson

unread,
Sep 6, 2002, 6:06:04 AM9/6/02
to
"Tripharn" <trip...@hotmail.com> wrote in message...

> I'm confused, how can AH=01H read a combination of CTRL-A, but not
CTRL by
> itself??

If I'm correct in assuming this, AH=01H may not be reading the CTRL
bit. 'A' however has an ASCII value (because it display's 'A' when we
press it). CTRL however doesn't has this, to tell if the CTRL has been
pressed then it's Scan Key Number needs to be read.

> Since I'm new to assembly, how do I read the Keyboard status flags?
So far
> I've got a program that reads the input from the keyboard, and
displays the
> make / break codes to the screen. I also at the same time have to
show if
> the shift, ctrl or alt is being pressed by displaying its binary
value in
> the top right of the screen.

There is a way of doing this with INT 16H, but I can't remember which
now, I use Ralf Browns interrupt
http://www-2.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html ) guide
whenever I need to check. You can download Interrupt list, Part A -> D
which should cover the the information you'll need.

Alternatively you can do a Google search ( http://www.google.com )
under "Ralf Brown" which uncovers numerous sites (including web based
interrupt guides).

Regards,
Ross.


Frank Kotler

unread,
Sep 6, 2002, 6:05:01 AM9/6/02
to
Tripharn wrote:

> I'm confused, how can AH=01H read a combination of CTRL-A, but not CTRL by
> itself??

Very roughly, when a key is pressed - or released - an interrupt is
generated. The interrupt is serviced by int 9. If a "regular" letter key
is pressed, it's scancode is converted to an ascii code (and if you
think about it, this ISR has to consult the status-flags to know if
"that key" needs to be translated to "a" or "A") and stored in the "type
ahead" buffer at 0040:001E (and updates a pointer to the buffer). If a
control or shift key (etc.) is pressed, there's nothing to store in the
buffer - the ISR just keeps track of whether it's currently up or down.
In the case of caps-lock, or insert (etc.) the "state" has to be toggled
and kept track of. This information is kept at 0040:0017, and since the
AT, 0040:0018. There's a lot of "housekeeping" to be done - resetting
the keyboard to accept another key, telling the programmable interrupt
controller that we're done, etc. but nothing further is done with the
key - it doesn't appear on the screen, or anything.

Int 16h is your interface with the information stored by the int 9 ISR.

Ah=1 looks to see if the "head pointer" and "tail pointer" into the
buffer are the same. If they are, no key is available, and the zero-flag
is set on return. If the pointers aren't the same, that means a key is
"available" - the ascii code and scan code are returned in al and ah,
zreo-flag cleared (NZ). The pointers aren't touched (so we didn't "get"
the key yet).

If ah=0, much the same thing happens, except that if a key isn't
available, we loop until one is (occasioned by the int 9 ISR updating
the "head" pointer when it gets an interrupt from the keyboard). Then
the codes are returned in al/ah, and the "tail" pointer is incremented.

If ah=2, the value at 0040:0017 - the keyboard status flags - is read
and returned in al. Adding 10h to any of these ah values will give you
the AT version of the int 16h routines. This just means a few more
oddball keystrokes will be picked up by ah=10h and ah=11h, but with
ah=12h it'll return those bits at 0040:0018 - which may be what you're
looking for - I assume in ah. I'm not certain, because I always read
0040:0017/18 direct from the bios data area. You can read the buffer and
handle the pointers yourself, too, but there's a lot more to it. Easier
to use int 16h for that.

You may have observed that if a key has been sitting in the buffer for a
while before being "gotten" by int 16h (or however) the status-flags
"now" may not match what they were when the key was pressed! The only
way I know around this is to not let it happen. Flush the buffer if
necessary, and only try to determine the "status" of a "freshly pressed"
key - as soon as it arrives.

> Since I'm new to assembly, how do I read the Keyboard status flags? So far
> I've got a program that reads the input from the keyboard, and displays the
> make / break codes to the screen.

Where are you getting these break codes? I was under the impression that
they were discarded, except for the ones that are tracked in the
status-flags. You can keep track of which keys are down, but I thought
you'd have to wedge into the int 9 ISR - not a task for a beginner.
There's an example in the AoA example code, named "int9.asm" IIRC, if
you need to do that.

> I also at the same time have to show if
> the shift, ctrl or alt is being pressed by displaying its binary value in
> the top right of the screen.

My example won't have to be modified very much to do that.

> I've almost completed except for getting the program to even register if the
> shift keys etc are being pressed. So reading the status flags would be
> simple, if I knew how.....

If you knew how, you wouldn't be writing the program :) Either int 16h
or reading the flags from the bda yourself should work. It sounds like
you're almost there.

Best,
Frank

Matthias Paul

unread,
Sep 6, 2002, 11:05:16 AM9/6/02
to
On 2002-09-06, Frank Kotler wrote:

> [Really good explanation skipped here]


>
> If ah=2, the value at 0040:0017 - the keyboard status flags - is read
> and returned in al. Adding 10h to any of these ah values will give
> you the AT version of the int 16h routines. This just means a few
> more oddball keystrokes will be picked up by ah=10h and ah=11h, but
> with ah=12h it'll return those bits at 0040:0018 - which may be what
> you're looking for - I assume in ah. I'm not certain, because I
> always read 0040:0017/18 direct from the bios data area. You can
> read the buffer and handle the pointers yourself, too, but there's
> a lot more to it. Easier to use int 16h for that.

Definitely, directly reading the buffer may cause problems when using
some less compatible keyboard buffer expanders.

I'd like to add that many programs decide between using the INT 16h/
AH=00h..02h and the newer INT 16h/AH=10h..12h function set by
checking the enhanced keyboard flag bit4 in 0040h:0096h.

Since RBIL 62 is still pending for release, I am providing some updated
info here, which builds on the info in the current issue RBIL 61:

|--------K-M00400096--------------------------
|MEM 0040h:0096h - KEYBOARD STATUS BYTE 1
|Size: BYTE
|SeeAlso: MEM 0040h:0097h,INT 16/AH=11h,INT 15/AH=4Fh
|
|Bitfields for keyboard status byte 1:
|Bit(s) Description (Table M0033)
| 7 =1 read-ID in progress
| 6 =1 last code read was first of two ID codes
| 5 =1 force Num Lock if read-ID and enhanced keyboard
| 4 =1 enhanced keyboard installed
| 3 =1 Right Alt pressed
| 2 =1 Right Ctrl pressed
| 1 =1 last code read was E0h
| 0 =1 last code read was E1h
|Note: the enhanced keyboard can be installed on XT, AT and later
| systems but not on original PC class systems.
|SeeAlso: #M0034,#M0010

If bit 4 is set, these drivers and programs will use the newer
functions. Since not all systems support this, there should be
some way to override this in both ways manually (some drivers
use /E to force usage of the new functions).

Most people are not aware of that on even newer systems, there is yet
another set of similar functions in the range AH=20h..22h. If it
is available, it should be used instead of AH=10h..12h (at least,
if a 122-key IBM Host Connected compatible keyboard is attached):

|--------B-1620-------------------------------
|INT 16 - KEYBOARD - GET 122-KEY KEYSTROKE (122-key kbd support only)
| AH = 20h
|Return: AH = BIOS scan code (see AH=10h)
| AL = ASCII character
|Notes: use AH=09h to determine whether this function is supported
| the 4DOS KSTACK 4.00A-7.01A (see INT 2Fh/AX=D44Fh) and the
| NDOS KSTACK v7.0+ (INT 2Fh/AX=E44Fh) do not support this
| function, but the FreeKEYB KSTACK emulation does.
|SeeAlso: AH=00h,AH=09h,AH=10h,AH=21h,AH=22h
|--------B-1621-------------------------------
|INT 16 - KEYBOARD - CHECK FOR 122-KEY KEYSTROKE (122-key kbd support
| AH = 21h only)
|Return: ZF set if no keystroke available
| ZF clear if keystroke available
| AH = BIOS scan code
| AL = ASCII character
|Notes: use AH=09h to determine whether this function is supported
| some versions of the IBM BIOS Technical Reference erroneously
| report that CF is returned instead of ZF
| K3PLUS v6.00+ supports this function as an alias of AH=11h
| the 4DOS KSTACK 4.00A-7.01A (see INT 2Fh/AX=D44Fh) and the NDOS
| KSTACK v7.0+ (INT 2Fh/AX=E44Fh) do not support this function,
| but the FreeKEYB KSTACK emulation does.
| some TSRs might trash BX and/or CX (see notes at INT 16/AH=11h)
|SeeAlso: AH=01h,AH=09h,AH=11h,AH=20h,AH=21h
|--------B-1622-------------------------------
|INT 16 - KEYBOARD - GET 122-KEY SHIFT STATUS (122-key kbd support
| AH = 22h only)
|Return: AL = shift flags 1 (see #00587)
| AH = shift flags 2 (see #00588)
|Notes: use AH=09h to determine whether this function is supported
| K3PLUS v6.00+ supports this function as an alias of AH=12h
| some TSRs might trash BX and/or CX (see notes at INT 16/AH=12h)
|SeeAlso: AH=02h,AH=09h,AH=12h,AH=20h,AH=21h

The availability of these functions (and keyboards) can be determinted
by utilizing the following INT 16h functions:

|--------B-1609-------------------------------
|INT 16 - KEYBOARD - GET KEYBOARD FUNCTIONALITY
| AH = 09h
|Return: AL = supported keyboard functions (see #00585)
| AH destroyed by many BIOSes
|Notes: this function is only available if bit 6 of the second feature
| byte returned by INT 15h/AH=C0h is set (see #00509)
| the Japanese MS-DOS 6.20 JKEYB.SYS hooks this function and
| always sets bit 4 on return (SeeAlso: AH=0Ah, INT 2Fh/
| AX=4FA0h).
|SeeAlso: AH=03h,AH=0Ah,AH=10h,AH=11h,AH=12h,AH=20h,AH=21h,AH=22h,
| INT 15/AH=C0h
|
|Bitfields for supported keyboard functions:
|Bit(s) Description (Table 00585)
| 7 reserved
| 6 INT 16h/AH=20h-22h supported (122-key keyboard support)
| 5 INT 16h/AH=10h-12h supported (enhanced keyboard support)
| 4 INT 16h/AH=0Ah supported
| 3 INT 16h/AX=0306h supported
| 2 INT 16h/AX=0305h supported
| 1 INT 16h/AX=0304h supported
| 0 INT 16h/AX=0300h supported
|SeeAlso: #00511
|--------K-160A-------------------------------
|INT 16 - KEYBOARD - GET KEYBOARD ID
| AH = 0Ah
|Return: BX = keyboard ID (see #00586)
| AH destroyed by many BIOSes
|Notes: check return value from AH=09h to determine whether this
| function is supported
| this function is also supported by the K3PLUS v6.00+ INT 16h
| BIOS replacement
| while this function is usually implemented in the ROM-BIOS,
| DBCS DOS drivers can also provide the functionality, even
| if not indicating this with INT 16h/AH=09h #00585. They
| require, however, that the keyboard ID byte at offset +117h
| in the extended BIOS data area (XBDA at INT 15h/AH=C1h) is
| updated to reflect the recorded keyboard ID. MS-DOS/PC DOS
| KEYB.COM takes care of this.
| this function is implemented by the Japanese MS-DOS 6.20
| JKEYB.SYS (SeeAlso: INT 2Fh/AX=AFA0h).
|SeeAlso: AH=09h,AX=AF4Dh,MEM 0040h:00C2h"AMI"
|
|(Table 00586)
|Values for keyboard ID:
|0000h no keyboard attached (or PC or AT keyboard attached)
| Key Tronic KB3270 PLUS 122-keys keyboard in "Native"/"IRMA"
| emulation
|41ABh MF2 keyboard (usually in translate mode)
| "US" G-layout keyboard (translate mode)
| Japanese G-layout keyboard (translate mode)
| Key Tronic KB3270 PLUS 122-key keyboard in "Enhanced 101"
| emulation
|54ABh Japanese P-layout keyboard (translate mode)
| "US" P-layout keyboard
|83ABh Japanese G-layout keyboard (pass-through mode)
| MF2 keyboard (pass-through mode)
| "US" G-layout keyboard (pass-through mode) (on "Patriot")
|84ABh Japanese P-layout keyboard (pass-through mode)
| "US" P-layout keyboard (pass-through mode) (on "Patriot")
|86ABh standard 122-key keyboard
|90ABh old Japanese G-layout DBCS keyboard
|91ABh old Japanese P-layout DBCS keyboard
|92ABh old Japanese A-layout DBCS keyboard
|Notes: the high byte of the keyboard ID is the second byte sent by the
| keyboard after a "read ID" command (see INT 09h table !!! at
| INT 2Fh/AX=AD80h)
| the Japanese MS-DOS 6.20 JKEYB.SYS never returns BX=0000h.
| If the keyboard ID would be undefined otherwise (that is
| 00ABh), it will return BX=41ABh instead.
| the Cherry G80-2550HPx "true" 122-key keyboard returns 86ABh,
| while the Key Tronic KB3270 PLUS keyboard with 122 keys
| returns 41ABh or 0000h depending on emulation mode, however,
| it doesn't emulate the the scancodes of a standard 122-key
| keyboard without reprogramming.
| the Key Tronic KB3270 PLUS keyboard has a unique keyboard
| command DAh 44h (see Table P0386) to report its current mode
| of operation.
|--------K-1692-------------------------------
|INT 16 - KEYB.COM KEYBOARD CAPABILITIES CHECK (not an actual
| AH = 92h function!)
|Return: AH <= 80h if enhanced keyboard functions (AH=10h-12h)
| supported
|Desc: this function is called by the DOS 3.2 KEYBxx.COM, the DOS 3.3+
| KEYB.COM, the Russian MS-DOS 5.0 KEYB.COM, and the Japanese
| MS-DOS 6.20 JKEYB.SYS in order to determine the highest
| supported keyboard function
|--------K-16A2-------------------------------
|INT 16 - KEYB.COM KEYBOARD CAPABILITIES CHECK (not an actual
| AH = A2h function!)
|Return: AH <= 80h if 122-key keyboard functions (AH=20h-22h) supported
|Desc: this function is called by the DOS 5+ KEYB.COM, including the
| Russian MS-DOS 5.0 KEYB.COM and the Japanese MS-DOS 6.20
| JKEYB.SYS in order to determine the highest supported
| keyboard function
---

Hope it helps,

Matthias

PS. If someone knows of additional keyboard IDs, please let me know.

--
<mailto:Matthi...@post.rwth-aachen.de>; <mailto:mp...@drdos.org>
http://www.uni-bonn.de/~uzs180/mpdokeng.html; http://mpaul.drdos.org
"Programs are poems for computers."


Frank Kotler

unread,
Sep 6, 2002, 2:50:06 PM9/6/02
to
Matthias Paul wrote:

>>[Really good explanation skipped here]

Whew! Thanks for the confirmation - I was afraid I'd screw it up
royally! And thanks for the additional info - snipped, but saved!

> "Programs are poems for computers."

Mine are just "jingles" :)

Best,
Frank

Reply all
Reply to author
Forward
0 new messages