BIOS Keystate Flags and You
by _y/YOSHi

Introduction.

See edit.com. Peaceful, serene edit.com. Edit.com, I think I love you. Anyways, the old, dos 5+ version of edit.com, not the new, arguably nicer Windows 95 version, had a nice feature: it kept track of keystates, and it told you when certain keys were active, or inactive, like all the lock keys and insert.

Well, BIOS tends to keep track of certain keys for you, and with a little talent, and/or a technical reference, or if you prefer, this text ("phlegm-text") will teach you how to reflect the states of these keys or change the states without much difficulty to you.

Essay.

Right. Now, BIOS has it's own special data-segment, it's 0040h. If you want to be technical about it, BIOS has several data segments, like 0F000h, 0040h, and various other little tidbits, but it keeps it's variables in 0040h. Included are the keystate flags.

Here is a list of the offsets into 0040h that can be of some use to you, assuming you plan to do something with the keyboard:

OffsetLength                 Value
17hByteKeyboard Shift State flags, #1
18hByteKeyboard Shift State flags, #2
19hByteAlt-Key work area
1ahWordHead Keyboard Buffer Pointer
1chWordTail Keyboard Buffer Pointer
1eh16 WordsKeyboard input buffer
71hByteControl-break flag
80hWordOffset of Keyboard Buffer
82hWordOffset of End of Keyboard Buffer
96hByteKeyboard Status Byte, #1
97hByteKeyboard Status Byte, #2

And this is all the keyboard information in the 0040h segment. It is your friend (if you live in an asylum).

Further analysis of these structures:

FORMAT OF 0040:0017 (BYTE)

76543210    Meaning
XInsert is active, if x=1, otherwise, inactive
XCaps Lock is active, if x=1, otherwise, inactive
XNum Lock is active, if x=1, otherwise, inactive
XScroll Lock is active, if x=1, otherwise, inactive
XAlt Key is pressed (x=1), or not pressed (x=0)
XCtrl Key is pressed (x=1), or not pressed (x=0)
XLeft Shift Key is pressed (x=1), or not pressed (x=0)
XRight Shift Key is pressed (x=1), or not pressed (x=0)

For your comprehension, a little program that shows how to fuddle with this data.

assuming ds is 40h, of course:

mov al, byte ptr ds:[17h]
or al, 0F0h
mov byte ptr ds:[17h], al

This code will read the byte at 40:0017 and set all the locks, as well as insert, and it will annoy the hell out of most people.

FORMAT OF 0040:0018 (BYTE)

76543210    Meaning
XInsert Key is pressed (x=1), or not pressed (x=0)
XCaps Lock is pressed (x=1), or not pressed (x=0)
XNum Lock is pressed (x=1), or not pressed (x=0)
XScroll Lock is pressed (x=1), or not pressed (x=0)
XA pause is in effect (x=1) (pause = ctrl-num lock)
XSysRq Key is pressed (x=1), or not pressed (x=0)
XLeft Alt Key is pressed (x=1), or not pressed (x=0)
XRight Alt Key is pressed (x=1), or not pressed (x=0)

This byte won't be really important to you, unless you rely on the ALT keys for menuing and such, in which case, the last two bits will be quite important to you. Here is some code to detect whether an alt key is pressed or not:

mov al, byte ptr ds:[18h]
and al, 3
or al, al
jnz @@some_alt_keys_are_pressed

The words at 1ah and 1ch are the head and tail pointers in the keyboard data. The head pointer points to the oldest key in the buffer, while the tail pointer points to the next availible word space to deposit a keystroke into. Here's some code that 'resets' the buffer:

mov ax, word ptr ds:[1ah]
mov word ptr ds:[1ch], ax

By setting the tail pointer equal to the head pointer, you can start the data over, in an essence. But who gives a shit? This is kind of boring. The most informative part of this document has passed in the first two analyses of the bytes at :0017 and :0018

:001E is the default for the start of the keyboard buffer, which means, this is where the data from keypresses accumulates, and if this isn't cleared periodically or if the data isn't read out of it, it will fill up. This is why if you type 16 characters while your machine is booting, the speaker will beep and anything after the 15th character you typed will be ignored. The remaining 15 characters will be dumped onto the command prompt immediately.

:0071 is the Ctrl-Break flag. If the user pressed control and break at the same time, ANY TIME SINCE THE OS BOOTED, this byte will be set to 80h. Note that this doesn't reset itself. You can do it manually, of course.

:0080 and :0082 contain the offsets of the keyboard storage area. These offsets are assumed to be in the segment :0040h, so don't do any funny stuff and try to make yourself a big buffer inside of your program. You'll most likely crash the machine badly. Note that these aren't the same as the head and tail pointers, :0080 is the start of the data area, not the start of the relative buffer inside of the data area, and :0082 is the end of the buffer, not the next availible space to deposit a character.

FORMAT OF 0040:0096 (BYTE)

76543210    Meaning
XThe keyboard id is being read (x=1)
XThe last keyboard code wasn't an id code
XForced num-lock condition is in action
XEnhanced keyboard (x=1), standard (x=0)
XRight Alt Key is pressed (x=1), or not pressed (x=0)
XRight Ctrl Key is pressed (x=1), or not pressed (x=0)
XThe last keyboard code recieved was 0e0h (x=1)
XThe last keyboard code recieved was 0e1h (x=1)

This is, for the most part, an utterly worthless byte. Almost as bad as this next one:

FORMAT OF 0040:0097 (BYTE)

76543210    Meaning
XAn error has occurred sending to the keyboard (x=1)
XThe LEDs on the keyboard are being updated (x=1)
XA resend request occured from the keyboard (x=1)
XAn acknowledge code was recieved from the keyboard (x=1)
XReserved
XThe Caps Lock LED is illuminated (x=1)
XThe Num Lock LED is illuminated (x=1)
XThe Scroll Lock LED is illuminated (x=1)

Why is this so worthless? Because, it's stupid information, and it's only for reference, you can't change this by setting the bits. Same thing with the last byte, that's why I didn't put anything between the formats of the two bytes.

Code.

I included some programs that you can look at as a reference, but they're both elementary stuff anyways, i.e. I went over it in this text.

References.

Wyatt, Allen L, Sr. _Advanced Assembly Language._ 1992. Que Corporation.

Greetings.

Zen/CrackZ, for not taking me seriously, ever .. that's a good thing, if you don't know me :-)

CoRN, for being so leet, I lub' ya to death, stay leet

Blorght, for being so blorghty, and where are you, anyways?

Cali, for being nice and giving me warez. Visit codeoasis.home.ml.org.

Vizion, for being there to talk to me after I smoke hash.

Tin, you may not be leet, and let's just leave it at that ;--)

Iczelion, please zip up your brain for me, I need a copy.

Same goes for The_Owl.

End.

That's the end of this document. I hope you can do something you couldn't before because of this. A lot of this information was taken from Wyatt's book in the references, but I think the book may be out of print... oh well.

_y/+YOSHi, 10:37 PM, 1/14/99