                      The Keyboard Interface Tutorial
                             By: Inbar Raz

Preface:

The Keyboard on the IBM PC and compatible is connected to the PPI -
Programmable Peripheral Interface, which generally takes care of Keyboard
functions, equipment information and timer functions. The PPI is addressable
via port reads and writes, to addresses 060h thru 063h.

There are several type of keyboards available. The main difference between the
various types is the key count. Existing sizez are:

83  Key (Original PC)
84  Key (XT and clones)
101 Key (Usually on AT's and up, called Enhanced Keyboard)

In addition to those standard types, there are numerous non-standard types,
which varry from manufacturer to manufacturer. There are 102 Key keyboards,
keyboards with two F-Key sets (upper and left), keyboards with weird
hardly-used keys like 'Macro' and 'Turbo' (which DO have a scan code, though)
etcetera.

The IBM AT and up provides a better way of negotiating the keyboard, by
allowing the user to directly access and command the keyboard, as it will be
demonstrated later.

Using assembly language, there are two major ways to handle the keyboard and
keystrokes:

1. Using DOS functions:

   DOS provides a useful set of functions to use in context with the keyboard.
   This includes one-key-input and string input.

2. Using BIOS interrupts:

   The IBM PC BIOS (Basic Input Output System) provides an interrupt to handle
   the keyboard - Interrupt 016h (022d). These functions, titles KEYBOARD I/O,
   are an efficient medium level way of using the keyboard

   In addition to the Interrupt 016h interface, there is the Keyboard
   Interrupt, Interrupt 009h. As opposed to the other interrupt, Interrupt
   009h is an IRQ - Interrupt Request, which means that it is never called by
   software. Only hardware, when certain conditions are met, calls IRQ
   interrupts. Naturally, the user is able to invoke them himself, but that is
   not commonly done.

3. Direct port access:

   It is possible to access the keyboard using direct port reads and writes.
   As mentioned before, this is usually done by addressing the PPI. On AT's
   and up, however, it is possible to directly access the keyboard itself.


The BIOS also supplies a certain amount of information about the keyboard
within it's BDA - BIOS Data Area, aka BDS - BIOS Data Segment - which is the
segment that lies at paragraph 040h (0040h:XXXXh or 0000h:04XXh):

Address Size Contents
  
0:0412    1  Errors in PCjr InfraRed keyboard link

0:0417    2  Keyboard status bits. See Keyboard Flags
0:0419    1  Current (accumulating) value of Alt+numpad pseudo-key input.
             Normally 0.  When [Alt] is released, value is stored in kbd buf.
0:041A    2  Address of keyboard buffer head (keystroke at that addr is next)
0:041C    2  Address of keyboard buffer tail
0:041E   32  Keyboard buffer.  BIOS stores keystrokes here (head and tail
             point to addresses from 041Eh to 043Dh inclusive).

0:0480    2  AT  PS/2 Keyboard buffer offset start address (usually 01Eh)
0:0482    2                                        end address (usually 03Eh)

0:0496    1  AT Keyboard flag bit 4=1 (10h) if 101-key keyboard is attached
0:0497    1  AT Keyboard flag for LED 'key lock' display
                  bits 0-2 are ScrollLock, NumLock, CapsLock respectively

******************************************************************************
******************************************************************************
******************************************************************************

Using DOS functions:
--------------------

DOS provides a set of 7 functions to handle the keyboard:

01h Keyboard Input
06h Console I/O
07h No Echo Unfiltered Input
08h No Echo Filtered Input
0Ah Buffered Input
0Bh Input Status
0Ch Clear Keyboard Buffer & Input


                          DOS Fn 01h: Keyboard Input


 Expects  AH     01h

 Returns  AL     Character fetched from the Standard Input


Description: Reads (waits for) a character from the Standard Input Device.
             Echoes that character to the Standard Output Device.
             If Ctrl-Break is detected, INT 23h is executed.

Notes:       Extended ASCII keystrokes (ie, F1-F12, PgUp, cursor, etc) will
             require two calls to this function.  The first call will return
             AL=0.  The second will return AL with the extended ASCII code.


                          DOS Fn 02h: Display Output


 Expects  AH     02h
Ķ DL     Character to send to the Standard Output

 Returns  none  


Description: Sends the character in DL to the Standard Output.

             Handles backspace (ASCII 8) by moving the cursor left and leaving
             the cursor there.

             If Ctrl-Break is detected, INT 23h is executed.


                           DOS Fn 06h: Console I/O


 Expects  AH     06h
Ķ DL     0 to 0FEh  Character to send to the Standard Output
                  0FFh       Request for input from the Standard Input

 Returns  ZF     Clear (NZ) if character is ready  on input requests
Ķ AL     Character read, if ZF is clear ͼ   (when DL=0FFh)
          

Description: If DL is 0FFh, this performs a "no wait" console input, returning
             the Zero Flag (ZF) set (ZR) if there is no character ready.
             If a character is ready, returns ZF cleared (NZ) with the
             character that was read in AL.

             If DL is anything but 0FFh, DL is sent to the Standard Output.

Notes:       Does not check for Ctrl-Break.  Call twice for Extended ASCII.


                 DOS Fn 07h: No Echo Unfiltered Console Input


 Expects  AH     07h

 Returns  AL     Character fetched from the Standard Input


Description: Reads (waits for) a character from the Standard Input Device,
             returning that character in AL.

             Unfiltered: Does not detect Ctrl-Break, backspace, etc.

Notes:       Call twice for Extended ASCII character input.
             Use Fn 0Bh to check status (if you don't want to wait for a key).


                      DOS Fn 08h: No Echo Console Input


 Expects  AH     08h

 Returns  AL     Character fetched from the Standard Input


Description: Reads (waits for) a character from the Standard Input Device,
             returning that character in AL.

             If Ctrl-Break is detected, INT 23h is executed.

Notes:       Call twice for Extended ASCII character input.


                      DOS Fn 0Ah: Buffered String Input


 Expects  AH     0Ah
Ķ DS:DX  Address of an input buffer (see below)

 Returns  none   Buffer contains input terminated with CR (ASCII 13h)


Description: On entry, the buffer at DS:DX must be set up as:
               
             max ?  ?   ?   ?   ?   ?     max is maximum acceptable input
                  (range: 1 to 254)
             On exit, the buffer is filled:
               
             maxlen T   E   X   T   0Dh   len is actual length of input,
                  less the terminating CR (eg, 4).

             Characters are read from the Standard Input up to a CR (ASCII 13)
             or up to the value of max-1.  If max-1 is reached, the console
             bell rings (beeps) for each character until Enter (CR) is read.

             The second byte of the buffer is filled with the actual length of
             the input, less the terminating CR.  The final character in the
             buffer is always CR (which is not counted in the length byte).

             The characters in the buffer (including the len) before the call
             are used as a "template" and the DOS editing keys are in effect:
             [Esc] displays "\" and restarts the edit, [F3] displays to the
             end of the template, [F5] displays "@" and stores the current
             line as the template, etc.  Most Extended ASCII keystrokes are
             ignored.

             If Ctrl-Break is detected, INT 23h is executed and the buffer is
             left unchanged.


                        DOS Fn 0Bh: Check Input Status


 Expects  AH     0Bh

 Returns  AL     0FFh if a character is available from the Standard Input
Ķ        0    if no character is available
          

Description: Checks the status of the Standard Input.

             If Ctrl-Break is detected, INT 23h is executed.

Notes:       Use before Fns 01h, 07h and 08h to avoid having DOS wait for a
             key.

             This is a simple, non-destructive way to check for Ctrl-Break
             during long calculations or other processing that does not
             normally look for input.  It lets the user abort from such a
             sequence.


                          DOS Fn 0Ch: Clear & Input


 Expects  AH     0Ch
Ķ AL     DOS input function number (01h, 06h, 07h, 08h, or 0Ah)

 Returns  none  


Description: Clears the Standard Input type-ahead buffer then invokes the DOS
             input function specified by AL.  This forces the system to wait
             for a character to be typed.

             These values are allowed for AL:  01h Keyboard Input
                                               06h Console I/O
                                               07h No Echo Unfiltered Input
                                               08h No Echo Filtered Input
                                               0Ah Buffered Input



In addition to these functions, it is also possible to read a selected amount
of characters from the keyboard, using DOS's File Handle functions, as the
Keyboard, aka Standard Input, has a pre-set handle of 0000h:

                    DOS Fn 3Fh: Read from keyboard via Handle


 Expects  AH     3Fh
Ķ BX     0000h - Handle for Standard Input (Keyboard)
           DS:DX  Address of buffer to receive data
           CX     Number of bytes to read

 Returns  AX     Error code if CF is set to CY
Ķ AX     Number of bytes actually read
          

Description: CX bytes of data are read from the keyboard. The data is placed
             into the caller's buffer pointed to by DS:DX.

Notes:       It is handy to use this function for reading default handles
             such as the Standard I/O handles, instead of the buffered input
             or character-by-character input functions.

             When you read from a device, AX returns the length of the line
             up to and including the termination CR (ASCII 13h).

******************************************************************************
******************************************************************************
******************************************************************************

Using BIOS Interrupts:
----------------------

As mentioned before, there are two ways to use interrupts to access the
keyboard.

The first is Interrupt 016h - Keyboard I/O.

                          INT 16h: Keyboard Services

 This is the application-level interface to the keyboard.  Keystrokes are
 actually processed asynchronously in the background.  As each keystroke is
 received from the keyboard, it is processed by INT 09h and placed into a
 circular queue.

 See AT Keyboard for ways to speed up the keyboard and other hardware info.

AH  Service
 
00h Read (wait for) next keystroke
    Output: AL = ASCII character  (if AL=0, AH is an Extended ASCII keystroke)
            AH = Scan Code or Extended ASCII keystroke

01h Check if a keystroke is ready (and preview it if so)
    Output: ZF = ZR = 1 if no key is ready
            ZF = NZ = 0 if a key is ready.
                        AX is set as for SubFn 00h (but the keystroke has not
                        been removed from the queue).

02h Read the shift-key status.  Determine which shift keys are currently being
     pressed and whether the keyboard is in NumLock state, etc.
    Output: AL = shift key and 'lock' status as in Keyboard Flags

03h Set keyboard typeamatic rate and delay. (11/15/85 BIOS)
     Input: AL = 05h (eg, AX = 0305h)
            BL = Typeamatic rate 0=30 rpts/sec, 1=26...1Fh=2. See AT Keyboard
            BH = Delay (0=250ms, 1=500ms, 2=750ms, 3=1 second)
    Output: (none)

04h (reserved)

05h Place a keystroke into the keyboard buffer. (11/15/85 BIOS)
    Input:  CL = ASCII character.
            CH = Scan Code  byte (or 0 if you don't care).
    Output: AL = Status: 0=success; 1=buffer full

06h-0Fh (reserved)

10h Read (wait for) a keystroke; specific for 101-key 'board (11/15/85 BIOS)
    Output: AL = ASCII character  (if AL=0, AH is an Extended ASCII keystroke)
            AH = Scan Code or translated Extended ASCII keystroke

11h Preview keystroke; same as 01, but for 101-key 'board (11/15/85 BIOS)
    Output: ZF = ZR = 1 if no key is ready
            ZF = NZ = 0 if a key is ready.
            AX is set as for SubFn 10f but keystroke is still in the buffer.

12h Read shift-key status; same as 02, but for 101-key 'board (11/15/85 BIOS)
    Output: AL = shift key and 'lock' status.  See 101-key  Keyboard Flags



The second is Interrupt 009h - Keyboard Interrupt, IRQ 1

                         INT 09h: Keyboard Interrupt

 This hardware-generated interrupt (IRQ 1) is executed upon each press and
 release of a key.  The ROM-BIOS code interprets the keystroke, storing values
 into the keyboard buffer at 0:041Eh.  It also handles the special cases of the
 PrtSc and SysReq keys, and tracks the status of the shift and case-lock keys.

See:  INT 16h .......... BIOS service to access the keys stored in the buffer
                         and obtain status of the certain shift keys.
      Scan Codes ....... a list of the values of each possible keystroke as
                         it is received by INT 09h.
      Extended ASCII ... for a summary of the values that BIOS stores into the
                         the keyboard buffer after it translates a scan code.
      Keyboard Flags ... for a summary of how to obtain, test for, and modify
                         the bit-settings of shift and case-lock flags.

 TSRs (RAM-resident programs) that have a hot-key to trigger a popup usually
 intercept INT 09h and test for a certain key with a sequence such as this:

         push    ax
         in      al,60h             ; Read the key
         cmp     al,POP_KEY         ; Is this the hot key?
         je      do_pop             ; Yes, trigger the popup
                                    ;  No, drop through to original driver
         pop     ax
         jmp     cs:[int9_vect]     ; Just hop out to original int handler

do_pop:  ;------ the following housekeeping is needed to satisfy the hdwr int

         in      al,61h             ; Get value of keyboard control lines
         mov     ah,al              ;  Save it
         or      al,80h             ; Set the "enable kbd" bit
         out     61h,al             ;  And write it out the control port
         xchg    ah,al              ; Fetch the original control port value
         out     61h,al             ;  And write it back

         mov     al,20h             ; Send End-Of-Interrupt signal
         out     20h,al             ;  to the 8259 Interrupt Controller

         ;------ other code handles other tests and finally the popup code

******************************************************************************
******************************************************************************
******************************************************************************

Direct port access:
-------------------

The keyboard is addressable in two manners.

The first, available on all IBM PCs of all types, is by addressing the PPI -
Programmable Peripheral Interface.

Port  Description
  
060h  PC/XT  PPI port A.  Read keyboard scan code:

      IN   al,60h  ; Fetche most recent scan code.  See INT 09h and Scan Code

      AT keyboard data register.                     See AT Keyboard

061h  PC/XT PPI (Programmable Peripheral Interface) port B.
      76543210
           0  
      ҽ bit
                0: Timer 2 gate (speaker)   OR 03h=speaker ON
               1: Timer 2 data  ͼ  AND 0FCh=speaker OFF
            3: 1=Read high switches; 0=read low switches(see 62h)
           4: 0=Enable RAM parity checking; 1=disable
          5: 0=Enable I/O channel check
         6: 0=Hold keyboard clock low
        7: 0=Enable keyboard; 1=disable keyboard



The second, available only on IBM PC/ATs and up, is by directly commanding the
keyboard itself. -= This is for the AT keyboard only. =-

Port  Description
  
064h  AT keyboard command register.  This port communicates with the 8042
      which runs an on-chip control program for the keyboard.  It accepts
      command codes and data bytes.

 The keyboard of the AT (and its Intel 8042 microcomputer interface) is
 programmable and a lot more interesting than the old-style PC keyboards.
 Using the information below, you can set the key repeat speed and play
 games with the "lock" key LED display.

 Note: This is not a comprehensive coverage of the details of keyboard and
       8042 operation, but it should provide some food for thought.

 Port 60h is for writing data and is maintained for compatibility with
 earlier models.  If the examples using port 64h don't work, try using 60h.

 Port 64h is for writing commands and data and for reading keyboard status.
 Before sending a command to the keyboard, the BIOS tests its status
 (IN al,64h) and makes sure a key isn't being pressed or the internal buffer
 isn't full, etc.  There's a small risk if you just go ahead and send the
 command:

       mov   al,cmd_code
       out   64h,al

 For a two-part command such as setting the typeamatic rate, it's wise to
 delay a little while between OUTs:

       mov   al,cmd_code
       out   64h,al
       mov   cx,2000h  ;arbitrary  10ms+
delay: loop  delay
       mov   al,data_value
       out   64h,al

Cmd  Description
 
0FFh Reset the keyboard and start internal diagnostics
0FEh Resend the last transmission
0FDh-0F7h (NOP)
0F6h Set keyboard to defaults and continue scanning
0F5h Set keyboard to defaults and disable keyboard scanning
0F4h Enable the keyboard. Kybd sends 'ACK', clears buffer, and starts scanning

0F3h Set typeamatic rate and delay.  First send 0F3h, then send data byte:

     76543210
     0dlyrept rate
     Ľ
       ˼  bits 0-4 set the repeat rate (see below)
         bits 5-6 set initial delay before first repeat:
                                00=250ms; 01=500ms; 10=750ms; 11=1000ms
       bit 7 is always 0
                                                    Value Rate    Value Rate
     This chart is a partial guide for the repeat    0  = 30.0    0Ah = 10.0
     rate (bits 0-4).  You can interpolate for       1  = 26.7    0Dh =  9.2
     values not shown, but let's face it, you're     2  = 24.0    10h =  7.5
     only interested in the fastest rates.           4  = 20.0    14h =  5.0
                                                     8  = 15.0    1Fh =  2.0

     The keyboard is initially set to begin repeating after 1/2-second and
     repeat at a rate of 10 repeats per second.  This is much too slow.  A
     data byte of 01h sets the delay to 1/4-second with 26 repeats per second.

0F2h-0EFh (NOP)
0EEh Echo.  Diagnostics aid.  Simply sends 0EEh right back.

0EDh Turn LED 'lock key' lights on or off. First send 0EDh, then send byte:

     76543210
      not usedcns
     ҽ
                   ScrollLock light 01h=turn on
                  NumLock light    02h=turn on
                 CapsLock light   04h=turn on

     The bit positions 0-3 correspond to bits 4-6 of the keyboard flags
     variable in the BIOS Data area.  You should make an effort to keep the
     flags in sync with the lights.  For instance, if you do a big favor for
     the user and set his ten-key pad into NumLock mode (by setting bit 5 of
     0:0417h) then be sure to turn on the corresponding LED (eg, bit 1).

******************************************************************************
******************************************************************************
******************************************************************************

                           Additional Information
                           ----------------------

                         Keyboard Shift Status Flags

 Two bytes at address 0:0417h and 0:0418h identify the status of the keyboard
 shift keys and keyboard toggles.  INT 16h returns the first byte in AL.

 76543210     Perform INT 16h Fn 02h
 I C N S a c sLsR     or fetch AL=byte at 0:0417h
 ҽ bit
                  0: Alpha-shift (right side) DOWN (AL & 01h)
                1: Alpha-shift (left side) DOWN  (AL & 02h)
              2: Ctrl-shift (either side) DOWN (AL & 04h)
            3: Alt-shift  (either side) DOWN (AL & 08h)
          4: ScrollLock state              (AL & 10h)
        5: NumLock state                 (AL & 20h)
      6: CapsLock state                (AL & 40h)
    7: Insert state                  (AL & 80h)

 76543210
 i c n s   syaLcL    fetch AL=byte at 0:0418h
 ҽ bit
                  0: Ctrl-shift (left side) DOWN (AL & 01h)
                1: Alt-shift (left side) DOWN  (AL & 02h)
              2: SysReq DOWN                 (AL & 04h)
            3: hold/pause state            (AL & 08h)
          4: ScrollLock DOWN             (AL & 10h)
        5: NumLock DOWN                (AL & 20h)
      6: CapsLock DOWN               (AL & 40h)
    7: Insert DOWN                 (AL & 80h)

Notes: Bits 0-2 of 0:0418h are defined only for the 101-key enhanced keyboard.

       The 101-key BIOS INT 16h Fn 12h returns AL as with Fn 02, but AH is
       returned with the following bit-flag layout:

       76543210
       syc n s aRcRaLcL    Perform INT 16h Fn 12h (101-key BIOS only)
       ҽ bit
                        0: Ctrl-shift (left side) DOWN  (AH & 01h)
                      1: Alt-shift (left side) DOWN   (AH & 02h)
                    2: Ctrl-shift (right side) DOWN (AH & 04h)
                  3: Alt-shift (right side) DOWN  (AH & 08h)
                4: ScrollLock DOWN              (AH & 10h)
              5: NumLock DOWN                 (AH & 20h)
            6: CapsLock DOWN                (AH & 40h)
          7: SysReq DOWN                  (AH & 80h)

       Some older programs change the values of NumLock and CapsLock state
       bits (at 0:0417h) to force a known status.  This is unwise because
       modern keyboards have indicator lights which will get out of sync with
       the status. See AT Keyboard for more information on the lock-key LEDs.

       PCjr status bytes at 0:0488 are omitted for lack of interest.


                             Keyboard Scan Codes

 When the keyboard forces a hardware interrupt, it passes a Scan Code to the
 interrupt handler.  The handler converts this to an ASCII or Extended ASCII
 value.  For compatibility across the various keyboards, it is wise to avoid
 using scan codes and stick to the BIOS translation of a keystroke.

Ŀ
 Original PC/XT Keyboard  When a key is released, the keyboard sends the
 same value, ORed with 80h (eg, [Ctrl] sends 1Dh
 when pressed and 9Dh when released).


Hex Dec Key Hex Dec Key  Hex Dec Key    Hex Dec Key     Hex Dec Key

01   1  Esc 12  18  E    23  35  H      34  52  . >     45  69  NumLock
02   2  1 ! 13  19  R    24  36  J      35  53  / ?     46  70  ScrollLock
03   3  2 @ 14  20  T    25  37  K      36  54  Shft(Rt)47  71  Home [7]
04   4  3 # 15  21  Y    26  38  L      37  55  * PrtSc 48  72  Up   [8]
05   5  4 $ 16  22  U    27  39  ; :    38  56  Alt     49  73  PgUp [9]
06   6  5 % 17  23  I    28  40  " '    39  57  spacebar4a  74  K -
07   7  6 ^ 18  24  O    29  41  ` ~    3a  58  CapsLock4b  75  Left [4]
08   8  7 & 19  25  P    2a  42  Shft(L)3b  59  F1      4c  76  Cntr [5]
09   9  8 * 1a  26  [ {  2b  43  \ |    3c  60  F2      4d  77  Rght [6]
0a  10  9 ( 1b  27  ] }  2c  44  Z      3d  61  F3      4e  78  K +
0b  11  0 ) 1c  28  Enter2d  45  X      3e  62  F4      4f  79  End  [1]
0c  12  - _ 1d  29  Ctrl 2e  46  C      3f  63  F5      50  80  Down [2]
0d  13  + = 1e  30  A    2f  47  V      40  64  F6      51  81  PgDn [3]
0e  14  bksp1f  31  S    30  48  B      41  65  F7      52  82  Ins  [0]
0f  15  Tab 20  32  D    31  49  N      42  66  F8      53  83  Del  [.]
10  16  Q   21  33  F    32  50  M      43  67  F9      
11  17  W   22  34  G    33  51  , <    44  68  F10     

                  K indicates a key on the numeric keypad

Ŀ
 84-Key AT Keyboard  The 84-key keyboard sends the same scan codes as the
 83-key (original PC) keyboard with the addition that
 [SysReq] sends scan code 54h (84 decimal).

 However, the BIOS never lets an application program see this scan code.
 Instead, it invokes INT 15h SubFn 85h on make or break of the SysReq key.

 The 'break' (release of a key) is handled differently.  Upon a break, the
 keyboard sends a two-byte sequence:  0F0h, followed by the 'make' scan code.
 See AT Keyboard Functions for information on programming this keyboard.

Ŀ
 101-Key Keyboard  This keyboard has three separate mappings of the scan
 codes, selected by communication through port 64h.  The
 keyboard comes to life with scan code set 2 (which is wildly different from
 the 84-key mapping.  However, the scan codes are translated by the hardware
 keyboard interface before they are made available to programs that read the
 keyboard.

 The result is that all of the scan codes identified in the above table are
 valid when the 101-key 'board comes up naturally.  The following table
 lists the additional scan-codes that are sent by the 101-key 'board.  Note
 that all keys mentioned here refer to the keys that are unique to this
 keyboard; eg, [Insert] is the dedicated insert key (not KeyPad Ins).

   
   Key                       Hex Sequence       Key           Hex Sequence
   
   F11 ..................... 57                 Home ........ E0 47
   F12 ..................... 58                 Shift-Home .. E0 AA E0 47
   Right-Alt ............... E0 38              End ......... E0 4f
   Right-Ctrl .............. E0 1D              Shift-End ... E0 AA E0 4f
   PrintScreen ............. E0 2A E0 37        Up........... E0 48
   Shft-PrintScreen (SysReq) E0 37              Shift-Up .... E0 AA E0 48
   Ctrl-PrintScreen (SysReq) E0 37              Down ........ E0 50
   Alt-PrintScreen ......... 54                 Shift-Down .. E0 AA E0 50
   Pause ................... E1 1D 45 E1 9D C5  PageUp ...... E0 49
   Ctrl-Pause (Break) ...... E0 46 E0 C6        Shft-PageUp . E0 AA E0 49
   Insert .................. E0 53              PageDown .... E0 51
   Shift-Insert ............ E0 AA E0 52        Shft-PageDown E0 AA E0 51
   Delete .................. E0 53              Right ....... E0 4D
   Shift-Delete ............ E0 AA E0 53        Shift-Right . E0 AA E0 4D
   Left .................... E0 4B              K Enter ..... E0 1C
   Shift-Left .............. E0 AA E0 4B        K / ......... E0 35
                                                Shift-K / ... E0 AA E0 35
   
                   K indicates a key on the numeric keypad

 Note that in cases where a key is similar to another (pre-101) key, the
 second scan code byte is the same as the original key.  Thus, some programs
 that work at the scan-code level can get away with simply ignoring the E0h
 prefix.


                          Extended ASCII Keystrokes


 When INT 16h Fn 00h returns AL=0, then AH will contain an extended ASCII
 keystroke as listed in these tables.  When a DOS Character I/O function
 returns a character of 00h, you should make a second call to obtain the
 extended ASCII value.

  ķ
   Key Hex Dec  Key       Hex Dec  Key       Hex Dec  Key      Hex Dec 
  Ķ
   F1   3B  59  Shift-F1   54  84  Ctrl-F1   5E   94  Alt-F1   68  104 
   F2   3C  60  Shift-F2   55  85  Ctrl-F2   5F   95  Alt-F2   69  105 
   F3   3D  61  Shift-F3   56  86  Ctrl-F3   60   96  Alt-F3   6A  106 
   F4   3E  62  Shift-F4   57  87  Ctrl-F4   61   97  Alt-F4   6B  107 
   F5   3F  63  Shift-F5   58  88  Ctrl-F5   62   98  Alt-F5   6C  108 
   F6   40  64  Shift-F6   59  89  Ctrl-F6   63   99  Alt-F6   6D  109 
   F7   41  65  Shift-F7   5A  90  Ctrl-F7   64  100  Alt-F7   6E  110 
   F8   42  66  Shift-F8   5B  91  Ctrl-F8   65  101  Alt-F8   6F  111 
   F9   43  67  Shift-F9   5C  92  Ctrl-F9   66  102  Alt-F9   70  112 
   F10  44  68  Shift-F10  5D  93  Ctrl-F10  67  103  Alt-F10  71  113 
  Ľ
  ķ
   Key   Hex  Dec Key   Hex  Dec  Key      Hex  Dec  Key      Hex  Dec 
  Ķ
   Alt-A  1E  30  Alt-P  19   25  Alt-3     7A  122  down      50   80 
   Alt-B  30  48  Alt-Q  10   16  Alt-4     7B  123  left      4B   75 
   Alt-C  2E  46  Alt-R  13   19  Alt-5     7C  124  right     4D   77 
   Alt-D  20  32  Alt-S  1F   31  Alt-6     7D  125  up        48   72 
   Alt-E  12  18  Alt-T  14   20  Alt-7     7E  126  End       4F   79 
   Alt-F  21  33  Alt-U  16   22  Alt-8     7F  127  Home      47   71 
   Alt-G  22  34  Alt-V  2F   47  Alt-9     80  128  PgDn      51   81 
   Alt-H  23  35  Alt-W  11   17  Alt--     82  130  PgUp      49   73 
   Alt-I  17  23  Alt-X  2D   45  Alt-=     83  131                    
   Alt-J  24  36  Alt-Y  15   21                     ^left     73  115 
   Alt-K  25  37  Alt-Z  2C   44  NUL       03    3  ^right    74  116 
   Alt-L  26  38                  Shift-Tab 0F   15  ^End      75  117 
   Alt-M  32  50  Alt-0  81  129  Ins       52   82  ^Home     77  119 
   Alt-N  31  49  Alt-1  78  120  Del       53   83  ^PgDn     76  118 
   Alt-O  18  24  Alt-2  79  121  ^PrtSc    72  114  ^PgUp     84  132 
  Ľ
              ͻ
               101-key Keyboard Extensions Supported by BIOS 
    ķ
     Key      Hex  Dec  Key           Hex Dec  Key           Hex  Dec 
    Ķ
     F11       85  133  Alt-Bksp      0E   14   Alt- K /      A4  164 
     F12       86  134  Alt-Enter     1C   28   Alt- K *      37   55 
     Shft-F11  87  135  Alt-Esc       01    1   Alt- K -      4A   74 
     Shft-F12  88  136  Alt-Tab       A5  165   Alt- K +      4E   78 
     Ctrl-F11  89  137  Ctrl-Tab      94  148   Alt- K Enter  A6  166 
     Ctrl-F12  8A  138                                                
     Alt-F11   8B  139  Alt-up        98  152  Ctrl- K /      95  149 
     Alt-F12   8C  140  Alt-down      A0  160  Ctrl- K *      96  150 
     Alt-[     1A   26  Alt-left      9B  155  Ctrl- K -      8E  142 
     Alt-]     1B   27  Alt-right     9D  157  Ctrl- K +      90  144 
     Alt-;     27   39                                                
     Alt-'     28   40  Alt-Delete    A3  163  Ctrl- K Up [8] 8D  141 
     Alt-`     29   41  Alt-End       9F  159  Ctrl- K Cn [5] 8F  143 
     Alt-\     2B   43  Alt-Home      97  151  Ctrl- K Dw [2] 91  145 
     Alt-,     33   51  Alt-Insert    A2  162  Ctrl- K Ins[0] 92  146 
     Alt-.     34   52  Alt-PageUp    99  153  Ctrl- K Del[.] 93  147 
     Alt-/     35   53  Alt-PageDown  A1  161                         
    Ľ
      K indicates a key on the numeric keypad (when not in NumLock mode)

==============================================================================

For any ideas, requests, corrections ("There is always one more bug") or
whatever, contant the author at:

Fido:

Inbar Raz, 2:401/100.1
Inbar Raz, 2:403/100.42

Internet:

nyvirus@weizmann.weizmann.ac.il
Inbar.Raz@p1.f100.n401.z2.fidonet.org
Inbar.Raz@p42.f100.n403.z2.fidonet.org

Snailmail:

Inbar Raz
5 Hanegev Street
Yavne 70600
