我正在尝试从GRUB 0.97(stage2_eltorito)切换到GRUB 2,生成启动操作系统的ISO映像。但是,我面临一个特殊的错误。为了给出一些上下文,我最近设置了一些异常处理ISR和两个IRQ:一个用于键盘输入,一个用于计时器滴答。使用GRUB Legacy启动时,内核工作正常,键盘输入也可以工作。当使用GRUB 2引导时,由于某种原因,内核会捕获常规保护错误异常并暂停系统。我已经多次校对我的代码,我无法在任何可能导致此GPF错误的地方找到错误。我的问题是什么,如何解决?这是内核的Assembly入口点,包括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
(我不认为这是一个多重启动问题,因为内核实际上在两种情况下都能完美加载) 这里提到的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;
}
当然,我的kmain
#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)
P.S:kvm -kernel
似乎有用......