No problem, I should have done so in the first place:
Code: Select all
_isr:
_isr0:
cli
push byte 0
push byte 0
jmp _isr
_isr1:
cli
push byte 0
push byte 1
jmp _isr
_isr2:
cli
push byte 0
push byte 2
jmp _isr
...
_isr31:
cli
push byte 0
push byte 31
jmp _isr
these are the blocks that I use to handle the interupts and they call:
Code: Select all
_isr:
mov [store1], eax
pop eax
mov [store2], eax
mov eax, [store1]
pusha
push es
push ds
push fs
push gs
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov eax, _int_handler
push dword [store2]
call eax
pop eax
pop gs
pop fs
pop ds
pop es
popa
add esp, 4
pop eax
inc eax
push eax
sti
iret
...
SECTION .data
...
store1 dd 0
store2 dd 0
int_handler:
Code: Select all
void int_handler(int err_code)
{
k_printf("\nKERNEL PANIC:", 0x04);
k_printf(exception_messages[err_code], 0x04);
return;
};
(exception_messages is a char* array)
In the code I used:
Code: Select all
volatile int test = 10;
....
test /= 0;
to cause a div 0 exception.
The first error was caused by the amount I added to esp at the end, because I used "push
byte", I assumed it only negate 1 from the stack, where as I now know it always negates 4, so by adding 4 to esp at the end to pass over the (error code/0 added to keep stack frame balanced), one can repair this error...
The second was because when the CPU calls the interrupt the value of the EIP that was pushed onto the stack was the address of the instuction that caused the error, so when i did an iret, it returned to that instruction, causing an exception loop...
So to work round this, I added code to increment the value of EIP that is on the stack by one (though of course this won't necessarily work as instructions have different lengths).
So for now i've decided to halt the CPU when an exception occurs in the kernel..., I'll change that when I get to implementing multi threading and user mode threads....
So the only reason that increasing the value of EIP used by iret by 1 worked was because the compiler converted:
into (something like):
So, the only reason this works is because 'div [reg]' happens to be 2 bytes long, and the second part was probably a 1byte opcode that didn't do anything much...
(So actually its a better idea to add 2 to the esp used by iret....)
But doing this is a bit pointless because if you miss out an instruction, this might interfere with the working off your kernel, so its better to hlt the CPU (which is what I now do after displaying the error message)
Thanks for all the help.
Jules