在汇编时定义IDT或在引导加载程序/内核中以编程方式在内存中构建它是否更实际?

时间:2015-04-02 04:43:30

标签: assembly kernel bootloader

在我看来,在为自己写一个完整的IDT时,还有很多工作要做。编写所有处理程序,等等。即使像宏观和"时代"指令来帮助你。如果是IDT 由256个qwords(或多或少)组成,用于保存有关用于调用的ir处理程序,标志,段选择器等的信息。让你自己进入pmode,选择一个内存位置并以编程方式创建你需要的所有内容会不容易?如果从地址0x7bfff开始,并构建所有256个条目,最多为0x7ffff,请确保为它们提供公共处理程序的地址,以便从,flags,selector,ect调用更具体的处理程序。然后你知道你的基础和限制。然后只需填写idt指针,加载它,并捕获它的工作原理。

1 个答案:

答案 0 :(得分:1)

实用性始终是主观感知。因此,您的问题无法完全回答。尽管如此,我们可以查看一些支持和反对在运行时构建中断描述符表(IDT)的参数:

基本上,您的问题归结为是否在运行或编译时生成常量数据(IDT)。假设将生成相同数量的数据,无论何时,我们都有一些常见的参数:

  • 程序大小:如果包含完全生成的数据,那么程序的大小(在本例中为内核)将会增加,从而导致可能更长的初始加载时间。当然,只有在数据可以通过与数据大小相比可以忽略不计的代码生成的情况下才会出现这种情况。
  • 执行时间:在运行时生成数据涉及"做东西",从而增加执行时间。根据生成数据所需的时间以及生成数据的频率,这可能是一个严重的问题,也可能是微不足道的。

在内核的上下文中,我可以想到以下情况需要在两个选项之间进行思考:

  • 内核的有限只读存储器(ROM)(以及其他代码)将被放入。在这种情况下,在运行时生成IDT有利于减少静态内存占用。除非在具有(非常)有限的内存的嵌入式设置中,否则不会发生这种情况。
  • 关键启动时间。如果在某些硬实时设置中,并且您的系统关闭(由于更新,故障......),那么您希望它尽快恢复。在运行时生成IDT可能会稍微增加启动时间。另一方面,加载静态数据也需要时间。恕我直言,你不太可能需要考虑这一点。

对于所有其他情况,在这样的"可衡量的"方面,并没有太大的区别。指标。考虑一下,有一些关于调试和运行时生成数据的权衡;使用静态IDT时,您甚至可以在运行内核之前对其进行验证。

这是实用性的另一个方面:

  

[..]编写所有处理程序,等等。即使像宏观和"时代"指令来帮助你。 [..]

这当然非常取决于您实际编写静态IDT的方式。基本上,没有人会阻止你编写一个(用户)程序来发出一个正确的IDT链接到你的内核,利用你将放入内核的相同代码(甚至更简单的代码)。因此,必须编写所有处理程序"是你的工具的缺陷,因此与在运行时是否生成它们没有直接关系。

hobbyist kernel I wrote long ago我创建的处理程序(代码)"手工" (我现在会这样做^^)和运行时的实际IDT(数据):

// src/idt/idt.c
void IDT_SetGate (UINT8 num, UINT base, UINT16 sel, UINT8 flags)
{
  UINT *tmp;    
  tmp = IDT;
  tmp += num * 2;   
  *tmp = (base & 0xFFFF);
  *tmp |= (sel & 0xFFFF) << 16;
  tmp++;
  *tmp = (flags & 0xFF) << 8;
  *tmp |= (base & 0xFFFF0000);
}

// src/int/isr.c
void ISR_Setup (void)
{
  IDT_SetGate(0, (unsigned)_isr0, 0x08, 0x8E);
  IDT_SetGate(1, (unsigned)_isr1, 0x08, 0x8E);
  // ... a lot more, an array would've been the better choice :D
}

然后我有了最小的处理程序_isr0_isr1,...在保存中断号并处理错误代码后调用了一个公共处理程序。这是反对的主要论据:

  

[..]确保为他们提供一个公共处理程序的地址,以便从[..]中调用更具体的处理程序

至少在x86上,您需要为不同的中断使用不同的处理程序,否则您无法分辨触发的中断。要在运行时真正生成处理程序,您需要某种专用的汇编程序,这有助于您在运行时生成代码。我不会称那个&#34;实用&#34;了。