I have been trying to loosely follow this tutorial on basic kernel dev. Currently, the target architecture is i386.
The implementation of IRQs is causing me issues ; my interrupt handler reports a cascade of Invalid Op Code
exceptions whenever I try to pass registers (defined as a struct
) as an argument to a function. Here is the code for the interrupt handler which raises the exception:
void interrupt_handler(registers_t all_registers) {
// Printing exception's name
kprint("interrupt_handler.c (l. 53) : Exception raised was:", 0xB0);
kprint(exception_messages[(int) all_registers.int_no], 0xB0);
kprint("\n", 0xB0);
// Celling test_handle to display the value of some registers
// INVALID OP CODE ================>
test_handle(all_registers); // works as expected if this line is commented out
}
void test_handle(registers_t all_registers) {
kprint("interrupt_handler.c (l. 78) : Register DS contains", 0xD0);
kprint("to be implemented", 0xD0);
}
The structure registers_t
is defined as follows (copied from the tutorial):
typedef struct {
u32int ds; /* Data segment selector */
u32int edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */
u32int int_no, err_code; /* Interrupt number and error code (if applicable) */
u32int eip, cs, eflags, useresp, ss; /* Pushed by the processor automatically */
} __attribute__((packed)) registers_t;
Trying function calling with other struct, I found that the number of variables in the struct
matters ; any struct
that has between 5 and 16 u32int triggers the exception. For instance, the following structure, when initialized and passed empty to test_handle
, does not raise exceptions:
// Same as registers_t with less arguments
typedef struct {
u32int ds;
u32int edi, esi;
} __attribute__((packed)) test_t;
Disassembling the .o file reveals that the generated code uses the mov
instruction to pass test_t
structures and movsd
to pass registers_t
. So my suspicion is that the compilation process is at fault, since the compiler generates unrecognized instructions.
Here are the relevant excerpts of my Makefile
:
C_FLAGS=-ffreestanding -nostartfiles -nodefaultlibs -fno-builtin -Wall -Wextra -fno-exceptions -m32 -target i386-pc-elf -fno-rtti
# Compiling C code
%.o: %.c
clang $(C_FLAGS) -c $< -o $@
# Linking
kernel/kernel.bin: $(O_FILES)
ld -o $@ -Ttext 0x1000 $^ --oformat binary -m elf_i386
Is there anything wrong about the compiling process? Or does the problem stem from elsewhere?