您遇到了众所周知的 x86 问题。我不相信链接器可以将 isr 例程的地址填充为 IDT 条目所期望的混合形式。
如果您雄心勃勃,您可以创建一个 IDT 构建器脚本来执行类似此(基于 Linux)的方法。我还没有测试过这个方案,无论如何它可能都是一种令人讨厌的黑客行为,所以要小心行事。
第 1 步:编写一个脚本来运行“nm”并捕获标准输出。
步骤 2:在脚本中,解析 nm 输出以获取所有中断服务例程的内存地址。
步骤 3:输出一个二进制文件“idt.bin”,其中 IDT 字节已全部设置并准备好执行 LIDT 指令。您的脚本显然以正确的混合形式输出 isr 地址。
第 4 步:使用 objcopy 将其原始二进制文件转换为 elf 部分:
objcopy -I binary -O elf32-i386 idt.bin idt.elf
第 5 步:现在 idt.elf 文件包含 IDT 二进制文件,其符号如下:
> nm idt.elf
000000000000000a D _binary_idt_bin_end
000000000000000a A _binary_idt_bin_size
0000000000000000 D _binary_idt_bin_start
第 6 步:重新链接您的二进制文件,包括 idt.elf。在程序集存根和链接器脚本中,您可以引用符号 _binary_idt_bin_start 作为 IDT 的基础。例如,您的链接器脚本可以将符号 _binary_idt_bin_start 放置在您喜欢的任何地址。
请注意,重新链接 IDT 部分不会移动二进制文件中的任何其他内容,例如你的 ISR 例程。通过将 IDT 放入其自己的专用部分,可以在链接器脚本(.ld 文件)中对此进行管理。
- -编辑 - -从评论来看,这个问题似乎很混乱。 32 位 x86 IDT 期望中断服务例程的地址被分成两个不同的 16 位字,如下所示:
31 16 15 0
+---------------+---------------+
| Address 31-16 | |
+---------------+---------------+
| | Address 15-0 |
+---------------+---------------+
因此,链接器无法像正常重定位那样插入 ISR 地址。因此,在启动时,软件必须构建这种分割格式,这会减慢启动时间。