【发布时间】:2021-03-06 20:49:50
【问题描述】:
我一直试图在基本内核开发上松散地关注this tutorial。目前,目标架构是 i386。
IRQ 的实现给我带来了问题;每当我尝试将寄存器(定义为struct)作为参数传递给函数时,我的中断处理程序都会报告一系列Invalid Op Code 异常。这是引发异常的中断处理程序的代码:
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);
}
结构体registers_t定义如下(抄自教程):
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;
尝试用其他结构调用函数,我发现struct中的变量数量很重要;任何具有 5 到 16 个 u32int 的 struct 都会触发异常。例如,以下结构在初始化并将空传递给 test_handle 时,不会引发异常:
// Same as registers_t with less arguments
typedef struct {
u32int ds;
u32int edi, esi;
} __attribute__((packed)) test_t;
反汇编 .o 文件显示生成的代码使用mov 指令传递test_t 结构和movsd 传递registers_t。所以我怀疑是编译过程有问题,因为编译器生成了无法识别的指令。
以下是我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
编译过程有什么问题吗?还是问题出在其他地方?
【问题讨论】:
-
您的异常处理程序应该收到错误地址。检查该地址处的指令。还可以考虑通过指针传递你的结构。
-
感谢您的建议!作为指针传递工作正常。我会尝试看看我是否能找出检索地址的代码,尽管“movsd”指令最有可能是可疑的,因为它是clang为
test_t和@987654338生成的代码之间唯一不同的地方@ -
我的猜测是编译器正在使用 SSE 指令复制结构,但您尚未启用 SSE 指令。
-
啊,我不知道SSE!不过好像是这样,谢谢!今天晚些时候我会写一个回复。
标签: c assembly clang osdev irq