COMMENT~

PROGRAM: SCS.ASM (Scan Code Sniffer)
 AUTHOR: Denis Boyles

RELEASE: Public Domain (pd) Dec 22, 1996
VERSION: 1.00a

COMPILE: Arrowsoft Assembler (MASM v3.0)
     OS: MS-DOS (v6.20)

PURPOSE: a quick keyboard scan code snooper for reference
  NOTES: ...A,A,A,BB,A,BB,A A,A,A,BB,A,BB,A...
~

;--------------------------------------
;define some constants for us
;--------------------------------------

if1

LF          EQU 00Ah                   ;define a line feed
CR          EQU 00Dh                   ;define a carriage return
DUL         EQU 024h                   ;define DOS ASCID terminator

endif


;--------------------------------------
;define default program segment
;--------------------------------------

PRG SEGMENT
    ASSUME CS:PRG,DS:PRG
    ORG 0100h

MAIN:
    jmp     short START                ;a short jump,hop & skip :) over data

OldKey      dw ?                       ;this and OldKey-2 for previous INT 9
ScanCode    db ?                       ;stores the currently pressed scancode

PrgMsg      db LF,"[Scan Code Sniffer] - Type away or press ESC to "
            db "quit the program.",CR,LF,LF,DUL

;--------------------------------------
;program really starts here
;--------------------------------------

START:
    mov     AH,009h                    ;DOS print an ASCID string
    mov     DX,offset PrgMsg           ;DS:DX -> string to print
    int     021h                       ;call DOS to print it

    mov     AX,03509h                  ;DOS get vector for INT 09 (keyboard)
    int     021h                       ;call DOS the get the current handler

    mov     word ptr OldKey-2,BX       ;save the offset into memory and
    mov     OldKey,ES                  ;save the segment into memory too

    mov     AX,02509h                  ;DOS set vector for INT 09 (keyboard)
    mov     DX,offset NewKey           ;DS:DX -> new handler routine
    int     021h                       ;call DOS to set new handler

S0:                                    ;our main program loop
    cmp     ScanCode,081h              ;was the ESC key released?
    jne     S0                         ;NO then keep looping until it is

    mov     AX,02509h                  ;DOS set vector for INT 09 (keyboard)
    lds     DX,dword ptr OldKey-2      ;DS:DX -> new handler routine
    int     021h                       ;call DOS to restore INT 09 handler

    mov     AX,04C00h                  ;DOS terminate program with code (0)
    int     021h                       ;call DOS to end the program

;--------------------------------------
;NewKey - our new INT 09 handler
;--------------------------------------

NewKey proc
    in      AL,060h                    ;read the scancode from the keyboard
    mov     ScanCode,AL                ;save it into memory for later

    mov     DH,AL                      ;put it into DH so we can
    call    PrnHex                     ;print it to screen as a hex value

    mov     AL,020h                    ;send an EOI to the PIC controller?
    out     020h,AL                    ;to say our handler is done
    iret
NewKey endp

;--------------------------------------
;PrnHex - prints out 8bit hex number
;   DH <= number to print
;--------------------------------------

PrnHex proc
    jmp     short PH0                  ;just a short jump over table data

HexTable    db "0123456789ABCDEF"      ;a table of `hex' characters :)

PH0:
    mov     SI,offset HexTable         ;set SI to point to our hex table
    xor     BX,BX                      ;zero out BX so we can use it later
    mov     AH,002h                    ;DOS print a single character

    mov     BL,DH                      ;copy byte to print into BL and
    mov     CL,4                       ;shift it right 4 places to extract
    shr     BL,CL                      ;the high nybble value so we can

    mov     DL,[SI+BX]                 ;get the character from our hex table
    int     021h                       ;which we print using DOS

    mov     BL,DH                      ;copy byte to print into BL again,now
    and     BL,00Fh                    ;AND off the high nybble leaving low

    mov     DL,[SI+BX]                 ;which we get the character from the
    int     021h                       ;table and call DOS to print that too

    mov     DL,020h                    ;then we print out two spaces to make
    int     021h                       ;the numbers into nice little columns
    int     021h                       ;for easier reading :)
    ret
PrnHex endp

PRG ENDS
END MAIN
