多年来,尤其是在x86操作系统开发中遇到的许多问题都激发了这个问题。最近,有关NASM的一个问题因修改而引起争议。在那种情况下,该人正在使用NASM并遇到汇编时间错误:
移位运算符只能应用于标量值
另一个相关问题是在编译时生成静态IDT时导致错误的GCC代码问题:
初始值设定项元素不是常量
在这两种情况下,此问题都与以下事实有关:IDT条目需要一个指向异常处理程序的地址,而GDT可能需要到另一个结构(如任务段结构(TSS))的基地址。通常这不是问题,因为链接过程可以通过重定位修复程序解析这些地址。对于IDT条目或GDT条目,这些字段将基地址/功能地址拆分开。没有重定位类型可以告诉链接程序将位移位,然后按照它们在GDT / IDT条目中的布局方式放置到内存中。彼得·科德斯(Peter Cordes)在这个答案中对此作了很好的解释。
我的问题是不是问这个问题是什么,但对于一个请求的功能,以及实用的解决方案的问题。尽管我对此进行了自我回答,但这只是许多可能的解决方案之一。我只要求提出的解决方案满足以下要求:
我以传统的引导加载程序1的形式提供了一些示例代码,该示例试图在组装时创建静态IDT和GDT,但是在与组装时会出现以下错误nasm -f elf32 -o boot.o boot.asm:
Run Code Online (Sandbox Code Playgroud)boot.asm:78: error: `&' operator may only be applied to scalar values boot.asm:78: error: `&' operator may only be applied to scalar values boot.asm:79: error: `&' operator may only be applied to scalar values boot.asm:79: error: `&' operator …
我编写了一些初始化IDT的代码,该IDT将32位地址存储在两个不相邻的16位半部分中。IDT可以存储在任何地方,您可以通过运行LIDT指令告诉CPU在哪里。
这是初始化表的代码:
void idt_init(void) {
/* Unfortunately, we can't write this as loops. The first option,
* initializing the IDT with the addresses, here looping over it, and
* reinitializing the descriptors didn't work because assigning a
* a uintptr_t (from (uintptr_t) handler_func) to a descr (a.k.a.
* uint64_t), according to the compiler, "isn't computable at load
* time."
* The second option, storing the addresses as a local array, simply is
* inefficient …Run Code Online (Sandbox Code Playgroud)