我正在开发一个 32 位操作系统,并开发了一个可以正常工作的 ELF 加载程序。现在我没有启用分页(我计划稍后,但现在我只是试图加载内核模块)并且我试图在启动时执行模块。基本上,由于此时多任务处理还没有完全实现,我只想加载每个模块,调用 init(它将安装中断处理程序并设置模块的用途)然后退出并执行下一个。它可以工作,但我不能用 C 程序中的指针做任何事情(因为它仍然认为它正在使用内核数据段)。所以基本上我想做的是创建一个新的数据段,指向 RAM 中的模块 .data 段。我通过在 GDT 中设置条目号 6 来做到这一点。
setGDTEntry(6, DataAddress,DataSize, 0xF2, 0xCF);
setEntry 方法工作得很好,看起来像
void setGDTEntry(int num, uint Base, uint limit, byte access, byte gran)
同样两者都可以 100% 工作,当我更改数据段选择器时会出现我遇到的问题。我在汇编中执行此操作,ELF 入口点存储在 EAX 中。
mov ax, 30h ; This is 8 * 6, the GDT entry containing the new data segment
mov ds, ax ; set data segment
call address ; JUMP!!!!
mov ax, 0x10 ; Restore kernel data segment
mov ds, ax ; set data segment
这将导致我的内核恐慌,给 CPU 异常 0x6,无效的操作码。我的 C 程序的源代码只是一个将文本复制到视频 RAM 的 hello world 程序(没什么可看的。)。有谁知道我做错了什么?我对 GDT 和段选择器的整个概念很陌生............而且我现在不能启用分页或多任务处理,我真的不想解释为什么......