以下是重置段的代码:
global reloadSegments
section .text
reloadSegments:
; Reload the CS register with an offset of 0x08
jmp 0x08:.reload_CS
.reload_CS:
; Reload data segment registers
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret
跳转本身就是导致操作系统崩溃的原因。以下是加载 gdt 的代码:
void lgdt(void* gdt, uint16_t size) {
gdtr.base = (uint32_t)gdt;
gdtr.limit = size-1;
asm __volatile__("lgdt (%0)" : : "r" (&gdtr));
}
基数是 32 位值,而极限是 16 位。下面是我调用两个函数并填充 gdt 的地方:
void initGdt() {
create_descriptor(0, 0, 0, 0);
create_descriptor(1, 0, 0x000FFFFF, (GDT_CODE_PL0));
create_descriptor(2, 0, 0x000FFFFF, (GDT_DATA_PL0));
create_descriptor(3, 0, 0x000FFFFF, (GDT_CODE_PL3));
create_descriptor(4, 0, 0x000FFFFF, (GDT_DATA_PL3));
lgdt(&gdt, sizeof(gdt)-1);
extern void reloadSegments();
reloadSegments();
}
创建描述符的函数和常量均来自 osdev.org 上的 gdt 教程。我使用 QEMU 作为具有多重引导的虚拟机。以下是该项目的 github 链接:https ://github.com/Wardence1/Basic_OS
我希望 os 能够成功跳转到 reload_CS 标签并重新加载 cs 寄存器,而不会出现问题。在此先感谢您的帮助!