2

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.

bad
  • 939
  • 6
  • 18
  • 1
    sounds right... but I don't see what you want to chain about it. You simply check the ports in the handler, store the info about key hit/release in a form as you want, and send the chip flag that the state change was handled and you are ready for next IRQ, and you can end the handler, in case there is another key already in queue, it will call the handler again. – Ped7g Feb 05 '18 at 23:42
  • 4
    Just an observation is that with the keyboard there is no **reliable** way to pass a character that was retrieved by the first interrupt routine in a chain to others. Once you read port 0x60 there is no guarantee that another handler will reliably retrieve the same value from the port again. It often works in virtual environment but not always on real hardware. – Michael Petch Feb 05 '18 at 23:46
  • 1
    Surprised this code works since you don't send an EOI (0x20 to port 0x20). – Michael Petch Feb 05 '18 at 23:48
  • 2
    `Int 9h` is the vector for IRQ1 (keyboard interrupt). You generally wouldn't call `int 9h`. If the keyboard interrupt (IRQ1) is ennaled on the PIC IRQ1 (int 9) routine will be called. Such a routine should not alter any registers. If it changes something it needs to restore them. Do not alter BP. – Michael Petch Feb 05 '18 at 23:51
  • But doesn't it execute automatically though? I'm not planning to call `int 9h` in my program. My thought was that `int 9h` is called by the ISR that handles the keyboard hardware interrupt. – bad Feb 05 '18 at 23:54
  • 1
    Usually an IRQ1 handler (int 9h) retrieves a character and puts the code into some type of structure. Often some variant of a ring buffer is used - but any structure that does the job will do. This allows the interrupt handler to do a minimum amount of work. A program that may sit in an infinite loop (one with a `hlt` instruction) can then read from the structure (circular buffer) and do what it must with the bytes found. – Michael Petch Feb 05 '18 at 23:54
  • 1
    Correct, you don't want to call `int 9h`. If the keyboard interrupt (IRQ1) is enabled on the PIC (Programmable Interrupt Controller) then the vector at `int 9` will be called. You process the character send an End of Interrupt to the PIC, and then do an `iret` to return. Any register(s) you change must be saved and restored otherwise weird and wonderful things will happen. – Michael Petch Feb 05 '18 at 23:56
  • 1
    You can check my answer focused on DOS game, where is probably working and correct keyboard handler (probably, because I didn't spend as much time on that answer, as I would love to, but it was confirmed by OP to work): https://stackoverflow.com/a/47115465/4271923 – Ped7g Feb 05 '18 at 23:57
  • @Micheal Petch - HANDLE_INPUT is just a procedure in my main program. It's not associated with `int 9h` yet. I was just showing my code, so I could explain the issues I'm having with it (below the code), and why I think chaining to `int 9h` may possibly solve those issues. – bad Feb 06 '18 at 00:00
  • 1
    Also I'm not sure how you want to exactly handle situations, when user will hit for example `A`, keep holding it, then press `B` shortly (so you will receive correct code + release), and the he will release `A` (the break with `A` doesn't correspond to anything any more, if you operate with single key buffer like `bp`). – Ped7g Feb 06 '18 at 00:08
  • 2
    either have map for all keys with on/off state or just for the keys used (like player controls) . Usually when you chain keyboard ISR then you don't mind that OS lose some of the key-hits as you use the results from first ISR in chain anyway. ... Here simple example of the [player controls](https://stackoverflow.com/a/29579522/2521214) – Spektre Feb 06 '18 at 08:42

0 Answers0