我一直在开发自己的操作系统,遵循 MULTIBOOT 标头和 GDT 的教程,但是当调用
gdt_flush
函数时,它会跳转到内存中的错误位置,在一个未定义的函数中,崩溃到 GRUB
(gdt.c)
#include "gdt.h"
struct gdt_entry_struct gdt_entries[5];
struct gdt_ptr_struct gdt_ptr;
extern void gdt_flush(addr_t);
void initGdt(){
gdt_ptr.limit = (sizeof(struct gdt_entry_struct) * 5) -1;
gdt_ptr.base = &gdt_entries;
setGdtGate(0,0,0,0,0); //Null Segment
setGdtGate(1,0,0xFFFFFFFF, 0x9A, 0xCF); //Kernel Code Segment
setGdtGate(2,0,0xFFFFFFFF, 0x92, 0xCF); //Kernel Data Segment
setGdtGate(3,0,0xFFFFFFFF, 0xFA, 0xCF); //User Code Segment
setGdtGate(4,0,0xFFFFFFFF, 0xF2, 0xCF); //User Data Segment
gdt_flush(&gdt_ptr); //Sends me into a random point in memory
}
void setGdtGate(uint32_t num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran){
gdt_entries[num].base_low = (base & 0xFFFF);
gdt_entries[num].base_middle = (base >> 16) & 0xFF;
gdt_entries[num].base_high = (base >> 24) & 0xFF;
gdt_entries[num].limit = (limit & 0xFFFF);
gdt_entries[num].flags = (limit >> 16) & 0x0F;
gdt_entries[num].flags |= (gran & 0x0F);
gdt_entries[num].access = access;
}
(gdt.s)
global gdt_flush
gdt_flush:
MOV eax, [esp+4]
LGDT [eax]
MOV eax, 0x10 ; Magic Numbers my old friend
MOV ds, ax
MOV es, ax
MOV fs, ax
MOV gs, ax
MOV ss, ax
JMP 0x08:.flush ; Magic Numbers Two Electric Boogaloo
.flush:
RET
(启动.s)
BITS 32
section .text
ALIGN 4
header:
dd 0x1BADB002 ; Magic number
dd 0x00000000 ; Flags
dd -(0x1BADB002+0x00000000); Checksum
dd header
dd header
dd data
dd stack_space
dd start
global start
extern kmain
start:
cli
mov esp, 0x90000
call kmain
hlt
halt_kernel:
cli
hlt
jmp halt_kernel
section .data
data:
section .bss
resb 8192
stack_space:
setGdtGate 函数上的拼写错误,是
gdt_entries[num].flags |= (gran & 0xF0);
,不是gdt_entries[num].flags |= (gran & 0x0F);
,已修复