Page 1 of 1

need help adding int 9 ISR to 'meaty skeleton'

Posted: Thu Jan 28, 2016 12:03 am
by bilsch01
I am running Ubuntu 14.04 on a 32-bit DELL laptop. I have the gcc cross compiler installed. I did OSDEV tutorial BARE BONES and moved on to MEATY SKELETON. I have done a lot of reading in OSDEV. The first thing to do seems to be to add an ISR to provide the kernel with input from the keyboard. Here's the program I made for installing the ISR for INT 9, which needs to be run during boot up:

Code: Select all


 global int9

SECTION	.text

int9:

mov ax,0xf000
mov ds,ax
mov byte [ds:00],0xfa
mov byte [ds:01],0x55
mov byte [ds:02],0x89
mov byte [ds:03],0xe5
mov byte [ds:04],0x1e
mov byte [ds:05],0xb8
mov byte [ds:06],0x00
mov byte [ds:07],0x00
mov byte [ds:08],0x8e
mov byte [ds:09],0xd8
mov byte [ds:10],0xb8
mov byte [ds:11],0x00
mov byte [ds:12],0x00
mov byte [ds:13],0x3e
mov byte [ds:14],0xa0
mov byte [ds:15],0x1e
mov byte [ds:16],0x04
mov byte [ds:17],0x1f
mov byte [ds:18],0x5d
mov byte [ds:19],0xfb
mov byte [ds:20],0xcf

mov ax,0
mov ds,ax
mov bx, 36				;9x4=36
mov byte [ds:bx+0],0x00
mov byte [ds:bx+1],0xf0
mov byte [ds:bx+2],0x00
mov byte [ds:bx+3],0x00

The 21 bytes of hex are this:

Code: Select all


cli
push bp
mov bp,sp
push ds
mov ax,0
mov ds,ax
mov ax,0
mov al,[ds:0x041e]
pop ds
pop bp
sti
iret
It reads the ascii byte stored in the screen buffer at address 0:041e and returns it to the OS in half register al. The correctness of that reasoning and the actual code are questionable, however that is not my question. I have two questions:

1) where do I put the int9 program (that needs to install the ISR at boot time) in the tree of the MEATY SKELETON and how do I get it to run at boot time?

2) how do I pass the returned byte into the tree of the MEATY SKELETON? There is no variable name for the byte and no name or label for the program (ISR) that returns it. I have studied the MEATY SKELETON and I see the likely places to pass it in are in tty.c or putchar.c. There's no way to do:

extern void int9(char c) - because there's no label int9.

TIA. Bill S.

Re: need help adding int 9 ISR to 'meaty skeleton'

Posted: Thu Jan 28, 2016 2:30 am
by Octocontrabass
bilsch01 wrote:1) where do I put the int9 program (that needs to install the ISR at boot time) in the tree of the MEATY SKELETON and how do I get it to run at boot time?
Your code is designed for real mode, but the Meaty Skeleton runs in protected mode. Putting it in Meaty Skeleton will be a lot more work than learning how to do it the right way.
bilsch01 wrote:2) how do I pass the returned byte into the tree of the MEATY SKELETON? There is no variable name for the byte and no name or label for the program (ISR) that returns it. I have studied the MEATY SKELETON and I see the likely places to pass it in are in tty.c or putchar.c. There's no way to do:

extern void int9(char c) - because there's no label int9.
Interrupt handlers are called by hardware, not by you. For example, your IRQ1 handler might fill a buffer with keypresses, and your "get key" function would empty that buffer. (This is just an example; your OS may do things differently.)

Even if you are in real mode, your code won't work for a few reasons.

Code: Select all

mov ax,0xf000
mov ds,ax
mov byte [ds:00],0xfa
You can't overwrite the BIOS ROM.

Code: Select all

mov ax,0
mov ds,ax
mov ax,0
mov al,[ds:0x041e]
The keyboard buffer at 0x0040:0x001E is filled by the BIOS IRQ1 (INT9) handler, so your replacement IRQ1 will never receive anything from the keyboard. Plus, you're modifying AX in an interrupt handler that could run at any time, possibly corrupting the value in AX while some other piece of code is using it.

Re: need help adding int 9 ISR to 'meaty skeleton'

Posted: Thu Jan 28, 2016 7:50 am
by bilsch01
If you have a minute I'd like to discuss this further. For talking purposes let's stay in real mode for a while. When a key is pressed (make or break) somehow the CPU knows to read the address stored at address 0:0024h and to execute the code at the stored address - which is the code for ISR 9. I, the OS programmer, have to write the the 4 byte address of ISR 9 at address 0:0024h Maybe the code of ISR 9 is in ROM BIOS. If it is, then I need to find its address somehow. Read the spec for the BIOS ? Maybe Ralph Brown's list?

I think ISR 9 reads the scan code from the keyboard controller. I think ISR 16 translates the scan code to ascii and stores it in the key buffer at 0040:001e - though I don't know the event that triggers ISR 16. To start out I need to know which ISRs are in ROM BIOS and which ones have to come from my OS. Perhaps all the ones for hardware are in BIOS.

Another question: I can't pass a byte from an ISR by using a CPU register, then I must need to create a space in the stack before 'push bp' and use that to pass the byte. Therefore the OS needs to know to pop the byte after the ISR returns. Is that how you do it?

Thanks. Bill S.

Re: need help adding int 9 ISR to 'meaty skeleton'

Posted: Thu Jan 28, 2016 8:42 am
by Brendan
Hi,
bilsch01 wrote:If you have a minute I'd like to discuss this further. For talking purposes let's stay in real mode for a while. When a key is pressed (make or break) somehow the CPU knows to read the address stored at address 0:0024h and to execute the code at the stored address - which is the code for ISR 9.
Full story: The keyboard is constantly "scanning" the keys. You can think of it as a grid of wires, a little like this:

Code: Select all

   A -----------O---O---O---
                |   |   |
   B -----------O---O---O---
                |   |   |
   C -----------O---O---O---
                |   |   |
                |   |   |
                0   1   2
By putting a signal through A and then reading at 0, 1 and 2, the keyboard can tell if a key on the top row is currently pressed. Then it can remove the signal from A and put a signal through B and see if a key on the second row is pressed.

There's a little controller built into the keyboard that does this. It also decides if something changed since last time, and if a key is different puts some bytes into an internal FIFO queue. Finally; the controller sends bytes (one bit at a time) to the computer (via. the keyboard cable).

Inside the computer there's another controller (the PS/2 controller) that monitors the port that the keyboard's cable is plugged into; and when it sees bits arriving it reconstructs them to create a byte, and stores that byte into its own "1 byte" buffer. Then it sends a signal to another chip to indicate that a byte has been received.

The other chip is an interrupt controller (e.g. PIC chip). It sees this "I want attention" signal and sets a flag. When it's ready (no higher priority IRQs in service, CPU running with interrupts enabled) it forwards the interrupt to the CPU and tells it which interrupt vector.

The CPU receives this from the interrupt controller, and goes looking in the IVT or IDT for the interrupt handler that corresponds to the interrupt vector; and starts the interrupt handler.
bilsch01 wrote:I, the OS programmer, have to write the the 4 byte address of ISR 9 at address 0:0024h Maybe the code of ISR 9 is in ROM BIOS. If it is, then I need to find its address somehow. Read the spec for the BIOS ? Maybe Ralph Brown's list?
The BIOS IVT is at 0x000000000 and has 4 bytes per entry, so the address of the IVT entry for interrupt 9 is at address 0x00000000 + 9 * 4 (or 0x00000024).

The interrupt handler for interrupt 9 would get the byte from the PS/2 controller, process it, and put a code into the BIOS's "keyboard buffer". These codes are not ASCII; mostly because ASCII can't represent things like "shift + F5". The BIOS's interrupt handler also does a few other things, like detecting if "contrl+alt+delete" was pressed (and rebooting), and detecting if "control+break" was pressed (and passing control to interrupt 0x1B if it was).

Eventually later maybe; software uses int 0x16 to call a BIOS function that fetches the next byte from the BIOS's "keyboard buffer".
bilsch01 wrote:To start out I need to know which ISRs are in ROM BIOS and which ones have to come from my OS. Perhaps all the ones for hardware are in BIOS.
Originally they're all in the BIOS (or in device ROMs); and initially (during early boot) you have to keep the BIOS happy. Later (when you're finished with the BIOS) you throw the BIOS in the trash and replace all of the interrupt handlers with your own. Then you laugh at how lame the BIOS was in comparison to your device drivers ("LOL, smelly old BIOS doesn't even support Unicode! Hehehe" :) ).
bilsch01 wrote:Another question: I can't pass a byte from an ISR by using a CPU register, then I must need to create a space in the stack before 'push bp' and use that to pass the byte. Therefore the OS needs to know to pop the byte after the ISR returns. Is that how you do it?
For IRQs, you have to return to the interrupted code as if nothing happened, with all registers containing the exact same values as they originally did. To transfer data you either store it in a buffer somewhere (for something else to fetch later), or use some sort of IPC to send the data.


Cheers,

Brendan

Re: need help adding int 9 ISR to 'meaty skeleton'

Posted: Thu Jan 28, 2016 8:54 am
by Octocontrabass
bilsch01 wrote:When a key is pressed (make or break) somehow the CPU knows to read the address stored at address 0:0024h and to execute the code at the stored address - which is the code for ISR 9.
During boot, the BIOS has programmed the keyboard controller to trigger IRQ1 when a key is pressed/released, the BIOS has programmed the interrupt controller to signal interrupt 9 to indicate IRQ1, and the BIOS has stored the address of its ISR 9 in RAM at 0:0x0024.
bilsch01 wrote:I, the OS programmer, have to write the the 4 byte address of ISR 9 at address 0:0024h
Assuming you want to write your own, instead of using the one provided by the BIOS, yes.
bilsch01 wrote:Maybe the code of ISR 9 is in ROM BIOS. If it is, then I need to find its address somehow.
The address of the BIOS ISR9 will be in RAM at 0:0x0024.
bilsch01 wrote:I think ISR 9 reads the scan code from the keyboard controller. I think ISR 16 translates the scan code to ascii and stores it in the key buffer at 0040:001e - though I don't know the event that triggers ISR 16.
ISR 9 reads the scan code from the keyboard controller, translates it if necessary, and stores it in the key buffer at 0x0040:0x001e. Software running on the computer (such as DOS) can call ISR 0x16 to read from that buffer.
bilsch01 wrote:To start out I need to know which ISRs are in ROM BIOS and which ones have to come from my OS. Perhaps all the ones for hardware are in BIOS.
The BIOS provides ISR 0 through 0x1F, 0x70 through 0x77, and maybe some others. Not all of them do anything interesting.
bilsch01 wrote:Another question: I can't pass a byte from an ISR by using a CPU register, then I must need to create a space in the stack before 'push bp' and use that to pass the byte. Therefore the OS needs to know to pop the byte after the ISR returns. Is that how you do it?
You can pass a byte from an ISR using a register, as long as that ISR is not triggered by a hardware IRQ. DOS INT 0x21 is a good example of this.


The BIOS is pretty much irrelevant in protected mode, so this is a waste of time unless you're either writing a real-mode OS or studying the PC architecture for fun. (I fall in the latter category.)

Re: need help adding int 9 ISR to 'meaty skeleton'

Posted: Thu Jan 28, 2016 10:48 am
by SpyderTL
In case it wasn't clear already, you don't need to handle interrupts in real mode, because BIOS will do that for you.

As soon as you enable Protected Mode, you have to handle your own interrupts. The BIOS will no longer help you.

Handling your own interrupts is a fairly complex task, but you don't really have any other option if you want to create your own OS, and you want access to more than 1 MB of RAM. :)

Re: need help adding int 9 ISR to 'meaty skeleton'

Posted: Thu Jan 28, 2016 11:25 am
by Schol-R-LEA
I was going to say that most of this is explained in the wiki pages on Interrupt Service Routines and Keyboard handling, but looking again much of it isn't explained as well there as it ought to be. I'll see if I can fix that when I get the chance; if anyone else can fix it before I get to it, please do.

Re: need help adding int 9 ISR to 'meaty skeleton'

Posted: Fri Jan 29, 2016 12:59 am
by bilsch01
In case it wasn't clear already, you don't need to handle interrupts in real mode, because BIOS will do that for you.
Is this true for all interrupts or hardware interrupts only?

Please disregard this question - it's stupid. Bill S.

Re: need help adding int 9 ISR to 'meaty skeleton'

Posted: Fri Jan 29, 2016 1:18 am
by bilsch01
Interrupt handlers are called by hardware, not by you. For example, your IRQ1 handler might fill a buffer with keypresses, and your "get key" function would empty that buffer. (This is just an example; your OS may do things differently.)
How can I know when there is something in the buffer to be read? Do I simply check it periodically or is there some event I can use? I think there's no choice but to check the buffer periodically.

Re: need help adding int 9 ISR to 'meaty skeleton'

Posted: Fri Jan 29, 2016 4:00 am
by Octocontrabass
In a multitasking operating system, you would put the thread waiting on keyboard input to sleep, and the keyboard interrupt handler will wake the threads waiting for input. (There are additional steps to this process, depending on how the OS is designed.)

In a monotasking operating system, you use a loop to check the keyboard buffer. This is how INT 0x16 AH=0x00 waits for input.

Re: need help adding int 9 ISR to 'meaty skeleton'

Posted: Fri Jan 29, 2016 9:31 pm
by SpyderTL
bilsch01 wrote:
Interrupt handlers are called by hardware, not by you. For example, your IRQ1 handler might fill a buffer with keypresses, and your "get key" function would empty that buffer. (This is just an example; your OS may do things differently.)
How can I know when there is something in the buffer to be read? Do I simply check it periodically or is there some event I can use? I think there's no choice but to check the buffer periodically.
It's entirely up to you. Both approaches will work, but both have advantages and disadvantages. For example, checking the ps/2 buffer for keyboard codes in a loop will max out your CPU, and it will reduce battery life on a laptop PC.

Generally speaking, handling interrupts is preferable to polling for input, however.