The following is the code for an int 9 handler. It allocates room for 256 keystrokes in its buffer. There are some differences from what you want. For one thing it was written for protected mode, so the handler is _isr29h, rather than _isr9h. For another thing the look up tables consist of 32 bit double words, rather than 16 bits words. Also it is assembled with masm, so the syntax differs slightly from nasm.
Code: Select all
.586P
DGROUP GROUP _DATA, _BSS
_TEXT SEGMENT PAGE PUBLIC USE32 'CODE'
assume cs:_TEXT, ds:DGROUP, es:DGROUP
;extrn _debug:near
_isr29h proc near
push eax
push ebx
push ecx
push edx
push esi
push edi
cld
in al, 60h ;read scan code from controller
cmp al, 53h ;scan code for Del key?
jne isr29_10 ;if not, don't chack for Ctrl+Alt+Del
mov cl, kbstat1 ;load shift key status byte
and and cl, 0c0h ;isolate the Ctrl and Alt bits
cmp cx, 0c0h ;was Ctrl+Alt+Del pressed?
jne isr29_10 ;if not proceed as normal
int 99h ;otherwise invoke handler
isr29_10:
call escape ;check for escape sequence
jc isr29_50 ;skip rest of handler if found and processed
call isLock ;check for a Caps Lock, Num Lock or Scroll Lock scan code
jc isr29_50 ;skip rest of handler if found and processed
call isShift ;check for a shift key scan code
jc isr29_50 ;skip rest of handler if found and processed
cmp kbcnt, 256 ;is the keyboard buffer full?
jne isr29_15 ;continue as normal if not
;sound speaker & exit ;therwise sound the speaker
jmp isr29_50 ;and exit
isr29_15:
test al, 80h ;key release scan code?
jnz isr29_50 ;exit handler if so
mov dl,al ;save scan code to dl
xovzx esi,al ;load esi with scan code
shl esi, 2 ;scale table index
lea ebx, scantbl ;ds:ebx -> vanilla flavour character codes ;
test kbstat1, 9 ;is shift key down?
jz isr29_20 ;if not, check whether Ctrl or Alt key is down
lea ebx, Shiftbl ;otherwise use Shift character codes
jmp short isr29_40
isr29_20:
test kbstat, 40h ;is Ctrl key down
jz isr29_30 ;if not, check whether Alt key is down
lea ebx, ctrltbl ;otherise use Ctrl character codes
jmp short isr29_40
isr29_30:
test kbstat, 80h ;is Alt key down? ;
jz isr29_40 ;if not use vanilla flavour table
lea ebx, alttbl ;otherwise use Alt codes
isr29_40:
mov eax, [ebx + esi] ;load character code
or eax,eax ;null character?
jz isr29_50 ;return from interrupt if so
call CapsLock ;adjust character codes as necessary if Caps Lock is on
call NumLock ;adjust character codes as necessary if Num Lock is on
mov edi, kbtail ;load edi with pointer to tail of keyboard queue
mov kbscan[edi], dl ;save scan code
shl edi, 2 ;scale for four byte characters
mov kbBuf[edi], eax ;save character code
inc kbCnt ;increment count of characters in buffer
inc kbtail ;increment tail pointer
and kbtail, 0ffh ;wrap around if necessary
int 4ah ;inform apps of a charters arrival in the buffer
isr29_50:
mov al, 20h
out 20h, al
pop edi
pop esi
pop edx
pop ecx
pop ebx
pop eax
iret
_isr29h endp
_isr49h proc near
iret
_isr49h endp
_isr4ah proc near
clc
retf 2
_isr4ah endp
CapsLock proc near
push ebx
push ecx
push edi
test kbstat2, 4 ;is Caps Lock on?
jz capl_1 ;if not, exit
lea edi, _caps_ ;es:edi -> array of scan/character codes
mov ecx, [edi] ;load ecx with size of array
add edi, 4 ;es:edi -> first element in array
repne scasd ;scan array for code in eax
jne capl_1 ;return to caller if not found
mov eax, [edi + 49] ;load upper case character
capl_1:
pop edi
pop ecx
pop ebx
ret
CapsLock near
NumLock proc near
push ebx
push ecx
push edi
test kbstat2, 2 ;is Num Lock on?
jz numl_1 ;if not exit
lea edi, _nums_ ;es:edi -> array of scan/character codes
mov ecx, [edi] ;load ecx with size of array
add edi, 4 ;es:edi -> first element of array
repne scasd ;scan array for code in eax
jne numl_1 ;return to caller if found
mov eax, [edi + 9] ;load numeric character
numl_1:
pop edi
pop ecx
pop ebx
ret
NumLock endp
SetLEDs proc near
push eax
out 60h, 0edh ;send set LEDs command to keyboard
led1:
in al, 64h ;read controller's status register
test al, 2 ;ready for input?
jnz led1 ;loop until it is
mov al, kbstat2 ;load al with status bits
out 60h, al ;send them to the keyboard
pop eax
ret
SetLEDs endp
isLock proc near
push eax
push ecx
push edi
mov ecx, 3 ;number of bytes to scan
lea edi, locks
repne scasb ;scan for a lock key scan code
clc
jne kbl_1 ;return to caller if not found
mov al, [edi + 2] ;otherwise load mask
xor kbstat2, al ;toggle flag
call SetLEDs ;update LEDs
stc ;and flag scan code found
kbl_1:
pop edi
pop ecx
pop eax
ret
isLock endp
isShift proc near
cmp al, 2ah ;LShift key press?
jne iss1 ;if not check for other shift keys
or kbstat1, 1 ;otherwise set LShift bit
jmp short iss8 ;and exit
iss1:
cmp al, 36h ;RShift key press?
jne iss2 ;if not check for other shift keys
or kbstat1, 8 ;otherwise set RShift bit
jmp short iss8 ;and exit
iss2:
cmp al, 1dh ;Ctrl key press?
jne iss3 ;if not check for other shift keys
or knstat1, 42h ;otherwise set the LCtrl and Ctrl bits
jmp short iss8 ;and exit
iss3:
cmp al, 38h ;Alt key press?
jne iss4 ;if not check for key release codes
or kbstat1, 84h ;otherwise set the LAlt and Alt bits
jmp short iss8 ;and exit
iss4:
cmp al, 0aah ;LShift release code?
jne iss5 ;if not check for other release codes
and kbstat1, 0feh ;otherwise clear LShift bit
jmp short iss8 ;and exit
iss5:
cmp al, 0b6h ;RShift release code?
jne iss6 ;if not check for other release codes
and kbstat1, 0f7h ;otherwise clear the RShift bit
jmp short iss8 ;and exit
iss6:
cmp al, 9dh ;LCtrl key release code?
jne iss7 ;if not check for LAlt release code
and kbstat1, 0fdh ;otherwise clear LCtrl bit
test kbstat1, 10h ;is RCtrl key down?
jnz iss8 ;exit if so
and kbstat1, 0efh ;otherwise clear the Ctrl key bit
jmp short iss8 ;and exit
iss7:
cmp al, 0b8h ;LAlt release code?
stc
jne iss9 ;if not return with carry clear (initially set)
and kbstat1, 0fbh ;otherwise clear LAlt bit
test kbstat1, 20h ;is RAlt key down?
jnz iss8 ;exit if so
and kbstat1, 7fh ;otherwise clear the Alt bit
iss8:
clc ;set carry if shift key found (initially clear)
iss9:
cmc ;complement carry flag
ret
isShift endp
ascape proc near
cmp _esc_, 1 ;was previous key press an escape code?
je esc1 ;if so process the scan code which has followed it
push eax
and al, 0feh ;clear bit 0 of al
cmp al, 0e0h ;escape code encountered?
pop eax
jne esc7 ;if not return to caller
mov _esc_, 1 ;otherwise set the escape flag
jmp short esc6 ;and return to caller
esc1:
cmp al, 1dh ;RCtrl key press?
jne esc2 ;if not check for RAlt key press
or kbstat1, 50h ;otherwise set the RCtrl and Ctrl bits
jmp short esc5 ;and return to caller
esc2:
cmp al, 38h ;RAlt key press?
jne esc3 ;if not check for key release codes
or kbstat1, 0a0h ;otherwise set the RAlt and Alt bits
jmp short esc5 ;and exit
esc3:
cmp al, 9dh ;RCtrl key release?
jne esc4
and kbstat1, 0efh ;if so clear the RCtrl bit
test kbstat1, 2 ;is the LCtrl key down?
jnz esc5 ;return to caller if it is
and kbstat1, 0bfh ;otherwise clear the Ctrl bit
jmp short ;and return to caller
esc4:
cmp al, 0b8h ;RAlt key release?
jne esc5 ;return to caller if not
and kbstat1, 0dfh ;otherwise clear the RAlt bit
test kbstat1, 4 ;is the LAlt key down?
jnz esc5 ;return to caller if so
and kbstat1, 7fh ;otherwise clear the Alt bit
esc5:
mov _esc_, 0 ;clear the escape flag to indicate no further escape codes expected
esc6:
stc ;set carry to indicate that part of an escape sequence has been processed
ret ;return to caller
esc7:
clc ;clear carry to indicate no escape codes have been processed
ret ;return to caller
escape endp
_isrvect proc near
;selector..............24
;offset................20
;seg16/seg32...........16
;priv..................12
;int number.............8
;eip....................4
push ebp
push eax
push ebx
push ecx
push edx
mov ebp,esp
mov ebx, [ebp + 8] ;load ebx with interrupt number
shl ebx, 3 ;calculate offset into interrupt vector table
add ebx, _kdata.idt_ptr ;add on base pointer for the table
mov al, [ebp + 16] ;load al with 16/32 segment size
sub al, 4
shr al, 1 ;convert to 6 for 16 bit seg, 14 for 32 bit
mov cl, [ebp + 12] ;load cl with privilege level
shl cl, 5 ;shift privilege into bits 5-6 of cl
or al.cl ;OR into al
or al, 80h ;set segment present bit
and al, 0efh ;clear bit 4
mov [ebx + 5], al ;load into flags field of descriptor
mov eax, [ebp + 20] ;load eax with vector
mov [ebx], ax ;copy lower word of vector into descriptor
shr eax, 16 ;shift upper word into ax
mov [ebx + 6], ax ;and copy it into the descriptor
mov ax, [ebp + 24] ;load ax with segment selector
mov [ebx + 2], ax ;and copy it into the interrupt descriptor
pop edx
pop ecx
pop ebx
pop eax
mov esp,ebp
pop ebp
ret
_isrvect endp
_isrEnable proc near
;irq
;eip
push ebp
mov ebp,esp
push eax
push edx
mov dx, [ebp + 8] ;load dx with mask
cmp dx, 80h ;does the irq line go to the slave PIC?
ja isrEn1 ;if so use code for the slave
in al, 21h ;read mask register of the master PIC
or al,dl ;OR in the mask bit
out 21h, al ;enable the relevant irq line
jmp short isrEn2 ;return to caller
isrEn1:
in al, 0a1h ;read the mask register of the slave PIC
or al,dh ;OR in the mask bit
out 0a1h, al ;enable the relevant irq line
isrEn2:
pop edx
pop eax
mov esp,ebp
pop ebp
ret
_isrEnable endp
_TEXT ENDS
_DATA SEGMENT PAGE 'DATA'
scantbl dd 0100001bh, 02000031h, 03000032h, 04000033h, 05000034h, 06000035h, 07000036h, 08000037h
dd 09000038h, 0a000039h, 0b000030h, 0c00002dh, 0d00003dh, 0e000008h, 0f000009h, 10000071h
dd 11000077h, 12000065h, 13000072h, 14000074h, 15000079h, 16000075h, 17000069h, 1800006fh
dd 19000070h, 1a00005bh, 1b00005dh, 1c00000dh, 00000000h, 1e000061h, 1f000073h, 20000064h
dd 21000066h, 22000067h, 23000068h, 2400006ah, 2500006bh, 2600006ch, 2700003bh, 28000027h
dd 29000060h, 00000000h, 2b00005ch, 2c00007ah, 2d000078h, 2e000063h, 2f000076h, 30000062h
dd 3100006eh, 3200006dh, 3300002ch, 3400002eh, 3500002fh, 00000000h, 3700002ah, 00000000h
dd 39000020h, 00000000h, 3b000000h, 3c000000h, 3d000000h, 3e000000h, 3f000000h, 40000000h
dd 41000000h, 42000000h, 43000000h, 44000000h, 00000000h, 00000000h, 47000000h, 48000000h
dd 49000000h, 4a00002dh, 4b000000h, 4c000000h, 4d000000h, 4e00002bh, 4f000000h, 50000000h
dd 51000000h, 52000000h, 53000000h
shiftbl dd 0100001bh, 02000021h, 03000040h, 04000023h, 05000024h, 06000025h, 0700005eh, 08000026h
dd 0900002ah, 0a000028h, 0b000029h, 0c00005fh, 0d00002bh, 0e000008h, 0f000000h, 10000051h
dd 11000057h, 12000045h, 13000052h, 14000054h, 15000059h, 16000055h, 17000049h, 1800004fh
dd 19000050h, 1a00007bh, 1b00007dh, 1c00000dh, 00000000h, 1e000041h, 1f000053h, 20000044h
dd 21000046h, 22000047h, 23000048h, 2400004ah, 2500004bh, 2600004ch, 2700003ah, 28000022h
dd 2900007eh, 00000000h, 2b00007ch, 2c00005ah, 2d000058h, 2e000043h, 2f000056h, 30000042h
dd 3100004eh, 3200004dh, 3300003ch, 3400003eh, 3500002fh, 00000000h, 00000000h, 00000000h
dd 39000020h, 00000000h, 3b000000h, 3c000000h, 3d000000h, 3e000000h, 3f000000h, 40000000h
dd 41000000h, 42000000h, 43000000h, 44000000h, 00000000h, 00000000h, 47000037h, 48000038h
dd 49000039h, 4a00002dh, 4b000034h, 4c000035h, 4d000036h, 4e00002bh, 4f000031h, 50000032h
dd 51000033h, 52000030h, 5300002eh
ctrltbl dd 0100001bh, 00000000h, 03000000h, 00000000h, 00000000h, 00000000h, 0700001eh, 00000000h
dd 00000000h, 00000000h, 00000000h, 0c00001fh, 00000000h, 0e00007fh, 00000000h, 10000011h
dd 11000017h, 12000005h, 13000012h, 14000014h, 15000019h, 16000015h, 17000009h, 1800000fh
dd 19000010h, 1a00001bh, 1b00001dh, 1c00000ah, 00000000h, 1e000001h, 1f000013h, 20000004h
dd 21000006h, 22000007h, 23000008h, 2400000ah, 2500000bh, 2600000ch, 00000000h, 00000000h
dd 00000000h, 00000000h, 2b00001ch, 2c00001ah, 2d000018h, 2e000003h, 2f000016h, 30000002h
dd 3100000eh, 3200000dh, 00000000h, 00000000h, 00000000h, 00000000h, 37000010h, 00000000h
dd 39000020h, 00000000h, 3b000000h, 3c000000h, 3d000000h, 3e000000h, 3f000000h, 40000000h
dd 41000000h, 42000000h, 43000000h, 44000000h, 00000000h, 00000000h, 77000000h, 00000000h
dd 84000000h, 00000000h, 73000000h, 00000000h, 74000000h, 00000000h, 75000000h, 00000000h
dd 76000000h, 00000000h, 00000000h
alttbl dd 00000000h, 78000000h, 79000000h, 7a000000h, 7b000000h, 7c000000h, 7d000000h, 7e000000h
dd 7f000000h, 80000000h, 81000000h, 82000000h, 83000000h, 00000000h, 00000000h, 10000000h
dd 11000000h, 12000000h, 13000000h, 14000000h, 15000000h, 16000000h, 17000000h, 18000000h
dd 19000000h, 00000000h, 00000000h, 00000000h, 00000000h, 1e000000h, 1f000000h, 20000000h
dd 21000000h, 22000000h, 23000000h, 24000000h, 25000000h, 26000000h, 00000000h, 00000000h
dd 00000000h, 00000000h, 00000000h, 2c000000h, 2d000000h, 2e000000h, 2f000000h, 30000000h
dd 31000000h, 32000000h, 00000000h. 00000000h, 00000000h, 00000000h, 00000000h, 00000000h
dd 00000000h, 00000000h, 3b000000h, 3c000000h, 3d000000h, 3e000000h, 3f000000h, 40000000h
dd 41000000h, 42000000h, 43000000h, 44000000h, 00000000h, 00000000h, 00000000h, 00000000h
dd 00000000h, 00000000h, 00000000h, 00000000h, 00000000h, 00000000h, 00000000h, 00000000h
dd 00000000h, 00000000h, 00000000h
dd 67 dup(?)
_caps_ dd 26, 1e000061h, 30000062h, 2e000063h, 20000064h, 12000065h, 21000066h
dd 22000067h, 23000068h, 17000069h, 2400006ah, 2500006bh, 2600006ch
dd 3200006dh, 3100006eh, 1800006fh, 19000070h, 10000071h, 13000072h
dd 1f000073h, 14000074h, 16000075h, 2f000076h, 11000077h, 2d000078h
dd 15000079h, 2c00007ah
dd 24 dup(?)
dd 1e000041h, 30000042h, 2e000043h, 20000044h, 12000045h, 21000046h
dd 22000047h, 23000048h, 17000049h, 2400004ah, 2500004bh, 2600004ch
dd 3200004dh, 3100004eh, 1800004fh, 19000050h, 10000051h, 13000052h
dd 1f000053h, 14000054h, 16000055h, 2f000056h, 11000057h, 2d000058h
dd 15000059h, 2c00005ah
dd 24 dup(?)
_nums_ dd 10 4f000000h, 50000000h, 51000000h, 4b000000h, 4c000000h, 4d000000h
dd 47000000h, 48000000h, 49000000h, 52000000h
dd 4f000031h, 50000032h, 51000033h, 4b000034h, 4c000035h, 4d000036h
dd 47000037h, 48000038h, 49000039h, 52000030h
dd
kbtail dd 0
kbhead dd 0
kbcnt dw 0
kbstat1 db 0 ;bit 0 - Left Shift down
;bit 1 - Left Ctrl down
;bit 2 - Left Alt down
;bit 3 - Right Shift down
;bit 4 - Right Ctrl down
;bit 5 - Right Alt down
;bit 6 - either Ctrl down
;bit 7 - either Alt down
kbstat2 db 0 ;bit 0 - Scroll lock on
;bit 1 = Num lock on
;bit 2 - Caps lock on
locks db 3ah, 45h, 46h
dw 4, 2, 1
_esc_ db 0
_fdCnt db 0
_DATA ENDS
_BSS SEGMENT PAGE PUBLIC USE32 'BSS'
kbBuf dd 256 dup(?)
kbscan db 256 dup(?)
_BSS ENDS