I'm writing a simple Operating system in assembly and c, but at the moment I'm stuck when implementing interrupts. When calling for example interrupt "int 0x02", the kernel prints the correct interrupt number, but cannot display the right error string and only prints an "S". What could be the problem here?
I'm following this tutorial: https://github.com/cfenollosa/os-tutorial
When I eventually had it working, I started adding IRQs, but when I did that, the printing of error strings stopped working again. I noticed that only deleting code from interupt.asm made it work again.
Snippet of isr.c:
void isr_install() { set_idt_gate(0, (u32)isr0); set_idt_gate(1, (u32)isr1); set_idt_gate(2, (u32)isr2); set_idt_gate(3, (u32)isr3); set_idt_gate(4, (u32)isr4); set_idt_gate(5, (u32)isr5); set_idt_gate(6, (u32)isr6); set_idt_gate(7, (u32)isr7); set_idt_gate(8, (u32)isr8); set_idt_gate(9, (u32)isr9); set_idt_gate(10, (u32)isr10); set_idt_gate(11, (u32)isr11); set_idt_gate(12, (u32)isr12); set_idt_gate(13, (u32)isr13); set_idt_gate(14, (u32)isr14); set_idt_gate(15, (u32)isr15); set_idt_gate(16, (u32)isr16); set_idt_gate(17, (u32)isr17); set_idt_gate(18, (u32)isr18); set_idt_gate(19, (u32)isr19); set_idt_gate(20, (u32)isr20); set_idt_gate(21, (u32)isr21); set_idt_gate(22, (u32)isr22); set_idt_gate(23, (u32)isr23); set_idt_gate(24, (u32)isr24); set_idt_gate(25, (u32)isr25); set_idt_gate(26, (u32)isr26); set_idt_gate(27, (u32)isr27); set_idt_gate(28, (u32)isr28); set_idt_gate(29, (u32)isr29); set_idt_gate(30, (u32)isr30); set_idt_gate(31, (u32)isr31); // Remap the PIC port_byte_out(PIC1_COMMAND, 0x11); port_byte_out(PIC2_COMMAND, 0x11); port_byte_out(PIC1_DATA, 0x20); port_byte_out(PIC2_DATA, 0x28); port_byte_out(PIC1_DATA, 0x04); //Tell master slave PIC at IRQ2 port_byte_out(PIC2_DATA, 0x02); //Tell slave cascade identity port_byte_out(PIC1_DATA, 0x01); //8086/88 (MCS-80/85) mode port_byte_out(PIC2_DATA, 0x01); //8086/88 (MCS-80/85) mode port_byte_out(PIC1_DATA, 0x0); //restore mask? port_byte_out(PIC2_DATA, 0x0); //restore mask? // Install the IRQs set_idt_gate(32, (u32)irq0); set_idt_gate(33, (u32)irq1); set_idt_gate(34, (u32)irq2); set_idt_gate(35, (u32)irq3); set_idt_gate(36, (u32)irq4); set_idt_gate(37, (u32)irq5); set_idt_gate(38, (u32)irq6); set_idt_gate(39, (u32)irq7); set_idt_gate(40, (u32)irq8); set_idt_gate(41, (u32)irq9); set_idt_gate(42, (u32)irq10); set_idt_gate(43, (u32)irq11); set_idt_gate(44, (u32)irq12); set_idt_gate(45, (u32)irq13); set_idt_gate(46, (u32)irq14); set_idt_gate(47, (u32)irq15); set_idt(); // Load with ASM}//list or error_messageschar *exception_messages[] = {"Division By Zero","Debug","Non Maskable Interrupt","Breakpoint","Into Detected Overflow","Out of Bounds","Invalid Opcode","No Coprocessor","Double Fault","Coprocessor Segment Overrun","Bad TSS","Segment Not Present","Stack Fault","General Protection Fault","Page Fault","Unknown Interrupt","Coprocessor Fault","Alignment Check","Machine Check","Reserved","Reserved","Reserved","Reserved","Reserved","Reserved","Reserved","Reserved","Reserved","Reserved","Reserved","Reserved","Reserved"};
interrupt.asm:
[extern isr_handler][extern irq_handler]; Common ISR code, all ISRs do thisisr_common_stub: ; 1. Save CPU state pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax mov ax, ds ; Lower 16-bits of eax = ds. push eax ; save the data segment descriptor mov ax, 0x10 ; kernel data segment descriptor mov ds, ax mov es, ax mov fs, ax mov gs, ax ; 2. Call C handler call isr_handler ; 3. Restore state pop eax mov ds, ax mov es, ax mov fs, ax mov gs, ax popa add esp, 8 ; Cleans up the pushed error code and pushed ISR number sti iret ; pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP and returns ; to where interrupt interrupted the kernel; Common IRQ code. Identical to ISR code except for the 'call'; and the 'pop ebx'irq_common_stub: pusha mov ax, ds push eax mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax call irq_handler ; Different than the ISR code pop ebx ; Different than the ISR code mov ds, bx mov es, bx mov fs, bx mov gs, bx popa add esp, 8 sti iret ;first make global, accessable for c codeglobal isr0global isr1global isr2global isr3global isr4global isr5global isr6global isr7global isr8global isr9global isr10global isr11global isr12global isr13global isr14global isr15global isr16global isr17global isr18global isr19global isr20global isr21global isr22global isr23global isr24global isr25global isr26global isr27global isr28global isr29global isr30global isr31global irq0global irq1global irq2global irq3global irq4global irq5global irq6global irq7global irq8global irq9global irq10global irq11global irq12global irq13global irq14global irq15; without push byte 0, cpu has already pushed the error; code onto the stack; 0: Divide By Zero Exceptionisr0: cli push byte 0 push byte 0 jmp isr_common_stub; 1: Debug Exceptionisr1: cli push byte 0 push byte 1 jmp isr_common_stub; 2: Non Maskable Interrupt Exceptionisr2: cli push byte 0 push byte 2 jmp isr_common_stub; 3: Int 3 Exceptionisr3: cli push byte 0 push byte 3 jmp isr_common_stub; 4: INTO Exceptionisr4: cli push byte 0 push byte 4 jmp isr_common_stub; 5: Out of Bounds Exceptionisr5: cli push byte 0 push byte 5 jmp isr_common_stub; 6: Invalid Opcode Exceptionisr6: cli push byte 0 push byte 6 jmp isr_common_stub; 7: Coprocessor Not Available Exceptionisr7: cli push byte 0 push byte 7 jmp isr_common_stub; 8: Double Fault Exception (With Error Code!)isr8: cli push byte 8 jmp isr_common_stub; 9: Coprocessor Segment Overrun Exceptionisr9: cli push byte 0 push byte 9 jmp isr_common_stub; 10: Bad TSS Exception (With Error Code!)isr10: cli push byte 10 jmp isr_common_stub; 11: Segment Not Present Exception (With Error Code!)isr11: cli push byte 11 jmp isr_common_stub; 12: Stack Fault Exception (With Error Code!)isr12: cli push byte 12 jmp isr_common_stub; 13: General Protection Fault Exception (With Error Code!)isr13: cli push byte 13 jmp isr_common_stub; 14: Page Fault Exception (With Error Code!)isr14: cli push byte 14 jmp isr_common_stub; 15: Reserved Exceptionisr15: cli push byte 0 push byte 15 jmp isr_common_stub; 16: Floating Point Exceptionisr16: cli push byte 0 push byte 16 jmp isr_common_stub; 17: Alignment Check Exceptionisr17: cli push byte 0 push byte 17 jmp isr_common_stub; 18: Machine Check Exceptionisr18: cli push byte 0 push byte 18 jmp isr_common_stub; 19: Reservedisr19: cli push byte 0 push byte 19 jmp isr_common_stub; 20: Reservedisr20: cli push byte 0 push byte 20 jmp isr_common_stub; 21: Reservedisr21: cli push byte 0 push byte 21 jmp isr_common_stub; 22: Reservedisr22: cli push byte 0 push byte 22 jmp isr_common_stub; 23: Reservedisr23: cli push byte 0 push byte 23 jmp isr_common_stub; 24: Reservedisr24: cli push byte 0 push byte 24 jmp isr_common_stub; 25: Reservedisr25: cli push byte 0 push byte 25 jmp isr_common_stub; 26: Reservedisr26: cli push byte 0 push byte 26 jmp isr_common_stub; 27: Reservedisr27: cli push byte 0 push byte 27 jmp isr_common_stub; 28: Reservedisr28: cli push byte 0 push byte 28 jmp isr_common_stub; 29: Reservedisr29: cli push byte 0 push byte 29 jmp isr_common_stub; 30: Reservedisr30: cli push byte 0 push byte 30 jmp isr_common_stub; 31: Reservedisr31: cli push byte 0 push byte 31 jmp isr_common_stub; IRQ handlersirq0: cli push byte 0 push byte 32 jmp irq_common_stubirq1: cli push byte 1 push byte 33 jmp irq_common_stubirq2: cli push byte 2 push byte 34 jmp irq_common_stubirq3: cli push byte 3 push byte 35 jmp irq_common_stubirq4: cli push byte 4 push byte 36 jmp irq_common_stubirq5: cli push byte 5 push byte 37 jmp irq_common_stubirq6: cli push byte 6 push byte 38 jmp irq_common_stubirq7: cli push byte 7 push byte 39 jmp irq_common_stubirq8: cli push byte 8 push byte 40 jmp irq_common_stubirq9: cli push byte 9 push byte 41 jmp irq_common_stubirq10: cli push byte 10 push byte 42 jmp irq_common_stubirq11: cli push byte 11 push byte 43 jmp irq_common_stubirq12: cli push byte 12 push byte 44 jmp irq_common_stubirq13: cli push byte 13 push byte 45 jmp irq_common_stubirq14: cli push byte 14 push byte 46 jmp irq_common_stubirq15: cli push byte 15 push byte 47 jmp irq_common_stub