Ok I looked at the assembler code of my kernel and here's what happens when I call the print or putc function inside my interrupt handler ...
Code:
extern void irq_handler(const registers_t r) {
// if interrupt was raised by slave PIC send EOI to slave
if (r.int_no >= 40) {
outb(0xa0, 0x20);
}
// send EOI to master
outb(0x20, 0x20);
// if interrupt handler exists, run it
//if (interrupt_handlers[r.int_no]) {
// interrupt_handlers[r.int_no](r);
//}
print("clk\n");
}
Code:
pusha
000000B6 1E push ds
000000B7 06 push es
000000B8 0FA0 push fs
000000BA 0FA8 push gs
000000BC 66B81000 mov ax,0x10
000000C0 8ED8 mov ds,ax
000000C2 8EC0 mov es,ax
000000C4 8EE0 mov fs,ax
000000C6 8EE8 mov gs,ax
000000C8 8925E2100000 mov [0x10e2],esp
000000CE E8E1140000 call 0x15b4
000000D3 0FA9 pop gs
000000D5 0FA1 pop fs
000000D7 07 pop es
000000D8 1F pop ds
000000D9 61 popa
000000DA 81C408000000 add esp,0x8
000000E0 FB sti
000000E1 CF iret
Code:
000015B4 83EC0C sub esp,byte +0xc
000015B7 837C244027 cmp dword [esp+0x40],byte +0x27
000015BC 7612 jna 0x15d0
000015BE 83EC08 sub esp,byte +0x8
000015C1 6A20 push byte +0x20
000015C3 68A0000000 push dword 0xa0
000015C8 E822EDFFFF call 0x1000002ef
000015CD 83C410 add esp,byte +0x10
000015D0 83EC08 sub esp,byte +0x8
000015D3 6A20 push byte +0x20
000015D5 6A20 push byte +0x20
000015D7 E813EDFFFF call 0x1000002ef
000015DC C7442420CB2D0000 mov dword [esp+0x20],0x2dcb
000015E4 83C41C add esp,byte +0x1c
000015E7 E9F0010000 jmp 0x17dc
The last instruction (jmp 0x17dc) jumps to the print function but it sets the argument first (mov [esp+0x20], 0x2dcb) but at esp+0x20 there is the value of GS which is poped before the iret instruction. So when 0x2dcb is poped into GS I obviously get a General protection fault.
Do you know how to tell the compiler to avoid that?