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