我正在尝试做一个简单的操作系统,我目前正在研究中断和IDT。
所以我实现了IDT和一个默认的异常处理程序,它目前什么也不做。
当我在bochs中运行我的操作系统时,我看到操作系统在跳转到内核时出现了三重错误。
bochs日志:
fetch_raw_descriptor: GDT: index (bf) 17 > limit (17)
interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
interrupt(): gate descriptor is not valid sys seg (vector=0x08)
字符串
异常0x0d是一般保护故障,所以我猜它与GDT有关,所以这里是我的GDT代码以及我如何加载它:
LoadGDT:
lgdt [g_GDTDesc]
ret
g_GDT:
; NULL descrytpor
dq 0
; 32 code segment
dw 0FFFFh ; limit
dw 0 ; base
db 0 ; base
db 10011010b ; access
db 11001111b ; granularity
db 0 ; base high
; 32 data segment
dw 0FFFFh ; limit
dw 0 ; base
db 0 ; base
db 10010010b ; access
db 11001111b ; granularity
db 0 ; base high
g_GDTDesc:
dw g_GDTDesc - g_GDT - 1 ; size of gdt
dd g_GDT ; address of gdt
型
但如果是因为IDT,那么我就遵循osDev wiki的this教程。
idt.c:
#define INTERRUPT_GATE_FLAGS 0x8e
typedef struct {
u16 isr_low; // lower 16 bit of ISR's address
u16 kernel_cs; // gdt segment selector
u8 reserved; // set to zero
u8 flags; // attribute flags
u16 isr_high; // higher 16 bit of ISR's address
} PACKED idt_entry_t;
typedef struct {
u16 limit;
u32 ptr;
} PACKED idtr_t;
__attribute__((aligned(0x10))) static idt_entry_t idt[256];
static idtr_t idtr;
void exception_handler(){
__asm__ volatile("cli; hlt"); // currently doe's nothing
}
void IDT_set_descriptor(u8 interrupt, void* isr, u8 flags){
idt_entry_t* descriptor = &idt[interrupt];
descriptor->isr_low = (u32)isr & 0xFFFF;
descriptor->kernel_cs = 0x08;
descriptor->reserved = 0;
descriptor->flags = flags;
descriptor->isr_high = ((u32)isr >> 16) & 0xFFFF;
}
extern void* isr_stub_table[];
void IDT_init(){
idtr.ptr = (u32)&idt[0];
idtr.limit = (u16)sizeof(idt) - 1;
for(u8 interrupt=0; interrupt<32; interrupt++){
IDT_set_descriptor(interrupt, isr_stub_table[interrupt], INTERRUPT_GATE_FLAGS);
}
__asm__ volatile("lidt %0": :"m"(idtr));
STI();
}
型
idt.asm:
; exceptions with error code
%macro isr_err_stub 1
isr_stub_%+%1:
call exception_handler
iret
%endmacro
; exceptions without error code
%macro isr_no_err_stub 1
isr_stub_%+%1:
call exception_handler
iret
%endmacro
extern exception_handler
isr_no_err_stub 0
isr_no_err_stub 1
isr_no_err_stub 2
isr_no_err_stub 3
......
isr_no_err_stub 29
isr_err_stub 30
isr_no_err_stub 31
; defining the isr_stub_table
global isr_stub_table
isr_stub_table:
%assign i 0
%rep 32
dd isr_stub_%+i
%assign i i+1
%endrep
型
1条答案
按热度按时间rggaifut1#
正如Michael Petch指出的,我的代码有两个主要问题。
第一个问题是,在我的 Boot 加载程序中,我只加载了一个扇区,尽管我的内核比这个扇区大。
第二个是在
link.ldt
中,我的链接脚本,我有:字符串
这意味着
.entry
段将在.text
段之前被链接。但是在
kernel_entry.asm
中,这是一个调用主内核函数的文件,我从.text
开始,所以我的内核没有正确链接。