Two bytes at address 0040:0017 and 0040:0018 identify the status of the
keyboard shift keys and keyboard toggles.

INT 16H 02H returns one byte in the AL register; it is exactly as found in
the byte at 0040:0017 in the BIOS Data Area:

KbdShiftFlagsRec
 7 6 5 4 3 2 1 0 
 i c n s A ^ S S 
             L R  bit mask
                  0:  01H alpha-shift (right side) DOWN
                  1:  02H alpha-shift (left side) DOWN
                  2:  04H Ctrl-shift (either side) DOWN
                  3:  08H Alt-shift  (either side) DOWN
                  4:  10H ScrollLock state
                  5:  20H NumLock state
                  6:  40H CapsLock state
                  7:  80H Insert state

INT 16H 12H returns 16 bits in the AX register.  It is similar to the word
at 0040:0017:

KbdShiftFlags101Rec
1 1 1 1 1 1
 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 
 q c n s A ^ A ^ i c n s A ^ S S 
 d d d d r r l l s s s s     L R  bit  mask
                                  0: 0001H alpha-shift (right side) DOWN
                                  1: 0002H alpha-shift (left side) DOWN
                                  2: 0004H Ctrl-shift (either side) DOWN
                                  3: 0008H Alt-shift  (either side) DOWN
                                  4: 0010H ScrollLock state
                                  5: 0020H NumLock state
                                  6: 0040H CapsLock state
                                  7: 0080H Insert state
                                  8: 0100H Ctrl-shift (left side) DOWN
                                  9: 0200H Alt-shift (left side) DOWN
                                 10: 0400H Ctrl-shift (right side) DOWN
                                 11: 0800H Alt-shift (right side) DOWN
                                 12: 1000H ScrollLock DOWN
                                 13: 2000H NumLock DOWN
                                 14: 4000H CapsLock DOWN
                                 15: 8000H SysReq DOWN

The byte at 0040:0018 is somewhat different from than that returned in
AH by INT 16H 12H.  Its layout is::

KbdShiftFlags0018Rec
 7 6 5 4 3 2 1 0 
 i c n s p q A ^ 
 d d d d   d l l  bit mask
                  0:  01H Ctrl-shift (left side) DOWN
                  1:  02H Alt-shift (left side) DOWN
                  2:  04H SysReq DOWN
                  3:  08H hold/pause state
                  4:  10H ScrollLock DOWN
                  5:  20H NumLock DOWN
                  6:  40H CapsLock DOWN
                  7:  80H Insert DOWN

Note: Bits 0-2 of 0:0418 are defined only for the 101-key enhanced
keyboard (older keyboards don't have two copies of Alt and Ctrl).

  NumLock and CapsLock Mode  
Bits 5-6 of 0040:0017 affect how the BIOS interprets certain keystrokes.

Each press of NumLock toggles bit 5.  When set, keys on the numeric keypad
are interpreted as digits 1-9 and period (.).  When bit 5 is clear, the
same keys are interpreted as cursor control keystrokes.

Each press of CapsLock toggles bit 6.  When set, alphabetic keys A-Z are
interpreted as uppercase (A-Z).  When bit 5 is clear, the same keys are
interpreted as lowercase (a-z).

Pressing the SHIFT key reverses the current sense of these "lock bits" so
that, for instance, in CapsLock mode, Shift+A result in lowercase 'a'.

  ScrollLock Mode  
The BIOS doesn't care about 0040:0017 bit 4 other than to toggle the bit
each time ScrollLock is pressed.  If you want your program to react to the
ScrollLock setting, you'll need to check this bit each time you process a
scrolling key.  Most programs don't bother.

  Insert Mode  
The BIOS toggles 0040:0017 bit 8 each time the Insert key is pressed.
Note that the BIOS also places the keycode for insert into the keyboard
buffer.  Most programs set bit 8 to a known state before processing input.

  LED Shift-State Indicators  
Starting with early AT keyboards, the status of CapsLock, NumLock, and
ScrollLock has been indicated by a light on the keyboard itself.  You can
program these lights using port I/O to talk to the keyboard controller.
See AT Keyboard for details.

However, recent BIOSes periodically update the keyboard LEDs, so just
setting or clearing bits of 0040:0017 will set the lights automatically.

  Detecting the press and release of Alt  
The BIOS does not put the Alt key or other shift keys into the keyboard
buffer.  If you want to take notice of the press (and release) of say,
Alt, you will need to either intercept INT 09H an read the raw scan codes,
or poll the byte at 0040:0017 regularly and watch for changes to the
keyboard flags.

See Also: AT Keyboard
- -

Keyboard Shift Status Flags