For the past couple of days I've been deeply researching the interrupt section of x86 processors.
As you are probably familiar with the fact that most of the people just slam some tutorial code together and somehow make it work. There isn't much that you can look at.
I am really struggling with my common interrupt exception handler (aka ISRs, I am not talking about interrupt requests doe), I am trying to understand how and why it works and I seem to be missing something crucial.
This is how it all looks inside my head:
1.When an interrupt exception gets triggered the CPU does this:
a) accesses the IDT and looks for the corresponding gate descriptor and if found calls it
b) pushes: SS (only valid when doing privilege level switching or in user mode), user_esp (only valid when doing privilege level switching or in user mode), EFLAGS, CS, EIP, Error Code (only some exceptions have it, if not I have to push a fake one).
2.I also need to push some things:
a) an interrupt number
b) general purpose registers (except EIP and ESP)
c) segment registers (except SS and CS)
3.I need to call an external high level handler
4.When it returns I need to:
a) pop everything back
b) add 8 bytes (2 variables worth) to ESP (effectively pop-ing the error code and interrupt number)
c) do an interrupt return call
I have a couple of distinguishable issues:
1.Exception 0 == Exception 6
Code: Select all
When I try to cause a division by zero error:
uint32_t test = 10;
uint32_t test_d = 0;
uint32_t something = test / test_d;
some_print_function(somethig, ...);
I get everything but division by zero...
But when I do this it works fine:
__asm__(int $0);
3.Only some values are correct, e.g. EAX, EDX, DS, FS, GS, CS are okay everything else is not, or it is of by a certain amount (EFLAGS in this case).
This is my code so far:
Code: Select all
push eax
push ecx
push edx
push ebx
push ebp
push esi
push edi
push ds
push es
push fs
push gs
;There is something that needs to go in here
call C_Interrupt_Service_Routine_Handler
;There is something that needs to go in here
pop gs
pop fs
pop es
pop ds
pop edi
pop esi
pop ebp
pop ebx
pop edx
pop ecx
pop eax
add esp, 4
add esp, 4
iretd
I've tried many solution but I don't know why would they work since I am not an Assembly guy.
Code: Select all
push esp
call C_Interrupt_Service_Routine_Handler
add esp, 4 (4 bytes because x86)
Both my GDT and IDT are set up correctly. (all my code, no tutorials only Intel manuals).
No, I did not forget a pointer. (registers_t* registers)
I need a solution for those problems and most importantly WHY does that specific solution work. (that is what I want to learn).
I hope that this post was informative enough for you guys to help me.
Btw this is what happens when I mess with Assembly, but I decided to mess with it and try to learn from my own mistakes.
Thanks!