Int 9h
is always called immediately after a new make/break code is made available at port 60h, right? If so, I intend to chain onto it so that my input code can react as soon as a new scancode is ready.
This webpage says, "When a key is pressed the keyboard sends the corresponding keyboard scancode to the keyboard controller, and the keyboard controller translates that and interrupts the CPU."
This pdf talks about in a little more detail (at the top of page 1155).
"When the scan code arrives at the PC, a second microcontroller chip receives the scan code, does a conversion on the scan code, makes the scan code available at I/O port 60h, and then interrupts the processor and leaves it up to the keyboard ISR to fetch the scan code from the I/O port."
It's talking about the int 9h
ISR, right?
Here's my input code. (It's just a procedure in my main program at the moment, it's not associated with int 9h
yet.) It takes a make code from port 60h, and makes it available globally in BP. It only accepts a break code if it corresponds with the previously collected make code.
HANDLE_INPUT PROC
;CLEARS THE KEYBOARD TYPEHEAD BUFFER AND COLLECTS A SCANCODE
;ALTERS BP
push ax
push bx
push es
;Clear the type ahead buffer to prevent the annoying PC speaker beep.
mov ax, 40h
mov es, ax ;access keyboard data area via segment 40h
mov WORD PTR es:[1ah], 1eh ;set the kbd buff head to start of buff
mov WORD PTR es:[1ch], 1eh ;set the kbd buff tail to same as buff head
;the keyboard typehead buffer is now cleared
;Collect scancode from port 60h.
;Always accept a make code.
;Only accept a break code if it corresponds with collected make code.
xor ah, ah
in al, 60h ;al -> scancode
test al, 80h ;Is a break code in al?
jz ACCEPT_KEY ;If not, accept it.
;If so, check to see if it's the break code
;that corresponds with the make code in bp.
mov bx, bp ;bx -> make code
or bl, 80h ;change make code into it's break code
cmp bl, al ;Do the new and old break codes match?
je ACCEPT_KEY ;If so, accept the break code.
pop es ;If not, bp retains make code.
pop bx
pop ax
ret
ACCEPT_KEY:
mov bp, ax ;bp -> scancode, accessible globally
pop es
pop bx
pop ax
ret
HANDLE_INPUT ENDP
The major flaw with this code is that make codes can appear and disappear from port 60h while the rest of my program is still executing. This is disastrous when a new key is pressed a fraction of a second before lifting my finger from the previous key. This leaves the break code that corresponds with the last detected make code waiting at port 60h, so the break code is accepted even though a new make code was available.
My hope is that I won't miss those split-second make codes if I chain to int 9h
.
And of course, the code will need to be modified before being chained to the interrupt. It's probably best to make the scancode available via a memory variable rather than BP among other things.