我正在尝试从 GRUB 0.97 (stage2_eltorito) 切换到 GRUB 2,生成一个引导操作系统的 ISO 映像。但是,我面临一个特殊的错误。只是为了提供一些上下文,我最近设置了一些异常处理 ISR 和两个 IRQ:一个用于键盘输入,一个用于计时器滴答声。当使用 GRUB Legacy 引导时,内核工作正常,键盘输入也工作。当使用 GRUB 2 引导时,出于某种原因,内核会捕获一般保护错误异常并停止系统。我已经多次校对我的代码,但在任何地方都找不到可能导致此 GPF 错误的错误。我的问题是什么,如何解决?这是内核的程序集入口点,包括 Multiboot 标头:
extern toc
extern init
extern kmain
extern load_gdt
global start32
MBALIGN equ 1<<0
MEMINFO equ 1<<1
MAGIC_NUMBER equ 0x1BADB002
FLAGS equ MBALIGN | MEMINFO
CHECKSUM equ -(MAGIC_NUMBER + FLAGS)
section .text
align 4
dd MAGIC_NUMBER
dd FLAGS
dd CHECKSUM
start32:
call load_gdt
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x9c000
call init
push ebx
call kmain
(我不认为这是 Multiboot 问题,因为内核实际上在这两种情况下都能完美加载)此处提到的 load_gdt 和相关标签(因为我认为这可能是问题的一部分)
global toc
global load_gdt
section .text
load_gdt:
lgdt[toc]
ret
section .rodata
gdt32:
dd 0
dd 0
dw 0x0FFFF
dw 0
db 0
db 0x9A
db 0xCF
db 0
dw 0x0FFFF
dw 0
db 0
db 0x92
db 0xCF
db 0
gdt_end:
toc:
dw gdt_end - gdt32 - 1
dd gdt32
设置操作系统的 init() 函数(当然,在我创建 initrd 之前)
#include <kernel.h>
void init()
{
interrupt_disable();
terminal_init(LGREEN, BLACK);
idt_install();
isr_install();
irq_install();
interrupt_enable();
timer_install();
keyboard_install();
return;
}
当然,我的主
#include <kernel.h>
#include <multiboot.h>
char logo[1024] = {
":::::::::::///oyhhyo//:::::::::::/:\n" \
"://////////+yNNmhysoo+////////////:\n" \
"::/://:://yNdy+//::::::+o/:://////:\n" \
"::////://sNdy+//::-:-:::++/://////:\n" \
"::::::://dmdyo/:::::--::++/::::::::\n" \
":::::::/+mdhhysoo+:/++//+y/::::::::\n" \
":::::::/oddyooo+/o//+so+/o/::::::::\n" \
"+ = = + + + +++++ Welcome to LunaOS!\n" \
"+ = = + + + +===+ A simple 32-bit operating system\n" \
"+ = = + + + + + Written soley by Safal Aryal\n" \
"++++++ = = = = + + + + All components of this OS,\n" \
":::::::/+hhyo///+s///::/+//:::::::: are in the public domain!\n" \
"::::::://oshs+/+hdhs+/////::::::::: (excluding the GRUB bootloader)\n" \
"::::::::/++so+shdyhys+////::::::::: Type `help` for a list of commands\n" \
"::::::::/+o++oosso++/+/:/::::::::::\n" \
":::::::/ossssysoso+//+/:/::::::::::\n" \
":::://ohysosysso+oo/:///:::::::::::\n" \
"::::--:/ssyoshhsoo+/::+:/-:::::::::\n" \
":::-----:+shysdyo/-.`-/::--:----:::\n" \
"--::------:+sssyo/.`.:/:----::-----\n" \
"-::/:--::-::---//////--------::----\n" \
};
void kmain(multiboot_info_t *mbd, uint32_t magic)
{
uint32_t mmap;
if((mbd->flags >> 6) & 1) {
mmap = mbd->mmap_addr;
}
terminal_puts(logo);
terminal_puts("SHELL> ");
for(;;){asm volatile("sti"); asm volatile ("hlt");};
}
提前致谢!(注意:multiboot_info_t 在我用来访问内存映射的 Multiboot 标头中定义,指向其类型的指针通过将 EBX 推送到 kernel.asm 中的堆栈作为参数传递给 kmain)
PS:kvm -kernel
似乎工作...