[英]Invalid Op Code Exception when implementing IRQs
I have been trying to loosely follow this tutorial on basic kernel dev.我一直试图在基本的 kernel 开发人员上松散地遵循本教程。 Currently, the target architecture is i386.目前,目标架构是 i386。
The implementation of IRQs is causing me issues; IRQ 的实施给我带来了问题; 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.每当我尝试将寄存器(定义为struct
)作为参数传递给 function 时,我的中断处理程序都会报告一系列Invalid Op Code
异常。 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):结构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;
Trying function calling with other struct, I found that the number of variables in the struct
matters;尝试使用其他结构调用 function ,我发现struct
中的变量数量很重要; any struct
that has between 5 and 16 u32int triggers the exception.任何具有 5 到 16 个 u32int 的struct
都会触发异常。 For instance, the following structure, when initialized and passed empty to test_handle
, does not raise exceptions:例如,以下结构在初始化并将空传递给test_handle
时,不会引发异常:
// 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
.反汇编 .o 文件显示生成的代码使用mov
指令传递test_t
结构, movsd
传递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
:以下是我的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?还是问题出在其他地方?
@Ross Ridge figured it out (thanks to him.). @Ross Ridge 想通了(感谢他。)。 The details below are what I learned from the OSDev wiki下面的细节是我从OSDev wiki学到的
The Streaming SIMD Extension (SSE) expands the set of instructions recognized by the CPU with some 70 additional instructions and adds some more registers.流式 SIMD 扩展(SSE) 扩展了 CPU 识别的指令集,增加了大约 70 条指令,并添加了更多寄存器。 SSE needs to be enabled before its instructions and registers can be used.需要先启用 SSE,然后才能使用其指令和寄存器。 The compiler generates machine code which can include SSE instructions and therefore, SSE needs to be enabled.编译器生成可以包含 SSE 指令的机器代码,因此需要启用 SSE。
In the code above, the passing of struct
to the function was compiled into machine code which involved the xmm0
register, which is part of the SSE.在上面的代码中,将struct
传递给 function 被编译为涉及xmm0
寄存器的机器代码,它是 SSE 的一部分。
The assembly code to enable SSE is given below (adapted from the OSDev wiki).下面给出了启用 SSE 的汇编代码(改编自 OSDev wiki)。 I added it to my bootloader, right after entering the 32-bit protected mode and before entering the kernel.在进入 32 位保护模式之后和进入 kernel 之前,我将它添加到我的引导加载程序中。 That fixed the problem!这解决了问题!
mov eax, cr0 ; cr0 cannot be manipulated directly, manipulate eax instead
and ax, 0xFFFB ; clear coprocessor emulation CR0.EM
or ax, 0x2 ; set coprocessor monitoring CR0.MP
mov cr0, eax
mov eax, cr4 ; cr4 too cannot be manipulated directly
or ax, 3 << 9 ; set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
mov cr4, eax
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.