C 如何通过将两个对象文件各自的部分放置在不同的位置来链接它们?

C 如何通过将两个对象文件各自的部分放置在不同的位置来链接它们?,c,assembly,linker,bootloader,linker-scripts,C,Assembly,Linker,Bootloader,Linker Scripts,我有一个引导加载程序“boot.asm”,它必须包含一个特殊的字,偏移量为510字节。我有一个用C编写的内核源代码“kernel.C” 我的计划是通过从bootloader程序加载硬盘的第二个扇区并将其放在内存中的0x8000位置来调用内核(将位于硬盘的第二个扇区) 现在,我正在将两个源文件编译成ELF对象文件(分别)到“boot.o”和“kernel.o”中,然后通过链接器链接它们并输出原始二进制文件“kernel.bin” 我想把我的引导加载程序代码从0x7c00开始,然后在0x7dfe位置

我有一个引导加载程序“boot.asm”,它必须包含一个特殊的字,偏移量为510字节。我有一个用C编写的内核源代码“kernel.C”

我的计划是通过从bootloader程序加载硬盘的第二个扇区并将其放在内存中的0x8000位置来调用内核(将位于硬盘的第二个扇区)

现在,我正在将两个源文件编译成ELF对象文件(分别)到“boot.o”和“kernel.o”中,然后通过链接器链接它们并输出原始二进制文件“kernel.bin”

我想把我的引导加载程序代码从0x7c00开始,然后在0x7dfe位置我必须把特殊的字。然后在0x8000,我必须放置我的内核代码。i、 我想把两个对象文件的各个部分放在不同的位置

这是我失败的尝试

ENTRY(boot)
OUTPUT_FORMAT("binary")

SECTIONS{
  . = 0x7c00;
  .text :
  {
    *(.boot)
  }

  .sig : AT(0x7dfe){
     SHORT(0xaa55);
  }

  . = 0x8000;

  .text :
  {
    kernel.o(.text)
  }

  .rodata :
  {
    kernel.o(.rodata)
  }

  .data :
  {
    kernel.o(.data)
  }

  .bss :
  {
    kernel.o(.bss)
  }

}
我所理解的是,一个可执行文件不能有一个节超过一次

我对低级编程的知识有限

我该如何解决这个问题。
谢谢。

您需要解决两件事,不要拆分
.text
输出部分,并使用
AT()
将内核立即放在启动扇区之后的输出二进制文件中,同时将其地址保持在0x8000。例如,类似这样的链接器脚本应该可以工作:

条目(启动)
输出_格式(“二进制”)
部分{
.=0x7c00;
.boot:
{
*(.靴子)
}
.=0x7dfe;
.sig:{
短(0xaa55);
}
.=0x8000;
.kernel:AT(0x7e00)/*位于引导扇区之后*/
{
*(.文本)
*(.罗达塔)
*(.数据)
_bss_开始=。;
*(.bss)
*(普通)
_bss_end=。;
}
内核扇区=(SIZEOF(.kernel)+511)/512;
/丢弃/:{
*(.eh_框架)
}
}

我添加了一些东西来处理GCC编译的对象文件中的部分。
\u bss\u start
\u bss\u end
符号可用于将
.bss
部分归零,根据Michael Petch的建议,将
内核扇区
符号设置为内核512字节扇区的长度。

通常的解决方案是将0xAA55幻数放入bootsector对象中。Ross Ridge,不仅如此,我还希望内核加载到位置0x8000,这是我在问题(现在编辑)中忘了提到的。另外一件你可能要考虑的事情是使用链接器脚本来计算内核所使用的数字扇区,并在Boo.asm中使用这些值。