TITLE kb_handler
DOSSEG
.MODEL SMALL
.STACK 100h
.DATA
b_khoff dw ? ;Backup keyboard handler offset
b_khseg dw ? ;Backup keyboard handler segment
b_thoff dw ? ;Backup time handler offset
b_thseg dw ? ;Backup time handler segment
f_stop db 0h ;Flag to stop the handler
f_shcap db 00h ;Flag Shift&Caps pressed
c_time db 0h ;Counter time
buff db 0h ;Last Scan Code buffer
endl db 10,13,"$" ;Endline
.CODE
EXTRN scan2a:PROC ;Scan to ascii
;
start: mov ax, @DATA ;Initialize
mov ds, ax ;DS
sub ax, ax ;Clear ax
;------------------------
;Saving Current Keyboard Handler
;------------------------
mov ax, 3509h ;ah=35:Get handler adress for int 09h (al=09)
int 21h ;call Dos function
mov b_khoff, bx ;Save Handler offset
mov b_khseg, es ;Save Handler segment
;------------------------
;Saving Current Time Handler
;------------------------
mov ax, 3508h ;ah=35:Get handler adress for int 08h (al=08)
int 21h ;call Dos function
mov b_thoff, bx ;Save Handler offset
mov b_thseg, es ;Save Handler segment
;
push ds ;Saving Current DS
mov ax, cs ;
mov ds, ax ;DS<-CS
;------------------------
;Replacing Keyboard Handler
;------------------------
mov dx, OFFSET KBHANDLER
mov ax, 2509h ;ah=25:Set handler adress for int 09h (al=09) at DS:DX
int 21h ;Call Dos function
;------------------------
;Replacing Time Handler
;------------------------
mov dx, OFFSET TMHANDLER
mov ax, 2508h ;ah=25:Set handler adress for int 08h (al=08) at DS:DX
int 21h ;Call Dos function
;------------------------
pop ds ;Restoring ds
;------------------------
main: mov cl, f_stop ;Check if Stop pressed
cmp cl, 1h ;1h=Stop program
jne main ;Loop
;------------------------
term: ;Restoring DOS Keyboard Handler
;------------------------
push ds ;Saving Current DS
mov dx, b_khoff ;DX<-Default handler Offset
mov ds, b_khseg ;DS<-Default handler Segment
mov ax, 2509h ;ah=25:Set handler adress for int 09h (al=09) at DS:DX
int 21h ;Call Dos function
pop ds ;Restoring ds
;------------------------
;Restoring DOS Time Handler
;------------------------
push ds ;Saving Current DS
mov dx, b_thoff ;DX<-Default handler Offset
mov ds, b_thseg ;DS<-Default handler Segment
mov ax, 2508h ;ah=25:Set handler adress for int 08h (al=08) at DS:DX
int 21h ;Call Dos function
pop ds ;Restoring ds
;------------------------
;End program
;------------------------
mov ax, 4C00h ;Dos END program arg
int 21h ;Call function
;----------------------------------------
;The Keyboard Handler proccess
KBHANDLER proc far ;Handlers are FAR processes
push ds ;
push ax ;Saving the registers
push bx ;which we ll use
push cx ;
push dx ;
;------------------------
;Preparations
;------------------------
mov ax, @DATA ;Initialize DS
mov ds, ax ;we ll use DATA segment
sub ax, ax ;Clear ax
;
sti ;Set Interrupt Flag (Enable Interrupts)
;------------------------
;THE HANDLER code
;------------------------
handle: in al, 60h ;Read Scan Code (port 60h=kb)
;
call CHECK ;Checking the code
cmp ah,00h ;if Didnt pass the check
je skip ;Skip the procedure
;------------------------
;Cheking for special keys
;------------------------
cmp al, 1h ;Escape key press
je escape ;
cmp al, 2Ah ;Shift key press
je shiftp ;
cmp al, 10101010b ;Shift key release
je shiftr ;
cmp al, 3Ah ;Caps key press
je capsp ;
cmp al, 1Ch ;Enter key press
je enter ;
cmp al, 80h ;Code of Release key, if above, ignore
jae skip ;skips procedure
;------------------------
conv: push ax ;Saving Scan code
mov dl, al ;Parameters Scancode
mov al, f_shcap ;Caps etc
call scan2a ;Convert to ascii
;------------------------
mov dl, al ;Giving the ascii as argument
mov ah, 02h ;Print letter
int 21h ;Call function
;------------------------
pop ax ;Restore scan code
;------------------------
;Saving cursor position
;------------------------
mov ah, 03h ;"Get Cursor"
mov bh, 0 ;"Display page"
int 10h ;Call the function
push dx ;Saving Coors
;------------------------
;Going to the corner
;------------------------
mov ah, 02h ;"Set Cursor position"
mov bh, 0 ;"Display page"
mov dh, 0 ;"Row"
mov dl, 78 ;"Column"
int 10h ;Call function
;------------------------
;al remained untouched, it has the Scan code
;------------------------
mov dx, ax ;Disphex arg
call Disphex ;Printing Scan code
;------------------------
pop dx ;Restoring Cursor pos
mov ah, 02h ;Set Cursor Position
mov bh, 0 ;Display page
int 10h ;Call funtion
;------------------------
cmp dl, 80d ;Check if EndOfLine
jne skip ;Finish procedure
enter: lea dx, endl ;Change Line
mov ah, 09h ;
int 21h ;
;------------------------
skip: mov al, 20h ;Signal to stop Handle
out 20h, al ;
;------------------------
pop dx ;
pop cx ;Restoring Used
pop bx ;Registers
pop ax ;
pop ds ;
iret ;IRET
;------------------------
;Special Keys
;------------------------
escape: mov cl, 1h ;
mov f_stop, cl ;Flag to terminate handler
jmp skip ;goto end
;------------------------
shiftp: push ax ;Saving
mov al, f_shcap ;
or al, 00000001b ;Parameters
mov f_shcap, al ;
pop ax ;Restore
jmp skip ;goto end
;------------------------
shiftr: push ax ;Saving
mov al, f_shcap ;
and al, 11111110b ;Parameters
mov f_shcap, al ;
pop ax ;Restore
jmp skip ;goto end
;------------------------
capsp: push ax ;Saving
mov al, f_shcap ;
mov ah, al ;
not ah ;Switch all bits
and ah, 00000010b ;Keep the 2nd bit of ah
and al, 11111101b ;Keep all others of al as they were
add al, ah ;add the 2nd bit of ah
mov f_shcap, al ;pass the arg.
pop ax ;Restore
jmp skip ;goto end
;------------------------
KBHANDLER endp
;----------------------------------------
;The Time Handler proccess
TMHANDLER proc far ;Handlers are FAR processes
push ds ;Saving the registers
push ax ;which we ll use
;------------------------
;Preparations
;------------------------
mov ax, @DATA ;Initialize DS
mov ds, ax ;we ll use DATA segment
sub ax, ax ;Clear ax
;------------------------
inc c_time ;Increase the counter
;------------------------
mov al, 20h ;Signal to stop Handle
out 20h, al ;
;------------------------
pop ax ;Restoring the
pop ds ;registers
iret ;IRET
TMHANDLER endp
;----------------------------------------
;The CHECK proccess Checks if same scan code and for how long pressed
; and lets Or not the character to pass to the handler
CHECK proc near
;Input: al : scan code
;Output: ah : 1h to continue or 0h not to
cmp al, buff ;Compare Scan code and Last scan code
je stp2 ;If equal, check time pressed
jmp succ ;Else, pass
;------------------------
stp2: mov ah, c_time ;Check Time that its pressed
cmp ah, 09h ;
jae succ ;If >9 pass
;------------------------
fail: mov ah, 00h ;Failure
retn ;Ending
succ: mov buff, al ;Refreshing "buff" to the new Scan code
mov c_time,00h ;Refreshing timer (to 0)
mov ah, 01h ;Success
retn ;Ending
CHECK endp
;----------------------------------------
;The disphex function
DispHex PROC NEAR
; Displays two hex digits
; Input: Byte to be displayed in DL (An integer mn)
; Output: None
; Uses: AX, CL, DX
push ax
push cx
push dx
mov cl, 4
xor dh, dh ; DX = 00mn
ror dx, cl ; DX = n00m
ror dh, cl ; DX = 0n0m
add dx, 3030h ; Convert m and n to ASCII (ASCII of "0" is 30h)
cmp dl, "9" ; if m>9 ...
jbe disp1
add dl, 7 ; ...then add 7 (ASCII of "A" is 41h = 3Ah + 7)
disp1: mov ah, 2
int 21h ; Display m
mov dl, dh ; Do the same for n
cmp dl, "9"
jbe disp2
add dl, 7
disp2: int 21h
pop dx
pop cx
pop ax
ret
DispHex ENDP
end start