我有一个引导加载程序“boot.asm”,它必须包含一个特殊字,位于距开头 510 字节的偏移量处。我有一个用 C 编写的内核源代码“kernel.c”。
我的计划是通过从引导加载程序加载硬盘的第二个扇区并将其放在内存中的 0x8000 位置来调用内核(它将位于 hd 的第二个扇区)。
现在我将两个源文件编译成 ELF 目标文件(分别)到“boot.o”和“kernel.o”中,然后通过链接器链接它们并输出原始二进制文件“kernel.bin”。
我想将我的引导加载程序代码从 0x7c00 开始,然后在 0x7dfe 位置我必须放置特殊的词。然后就在 0x8000 处,我必须放置我的内核代码。即我想将两个目标文件的各个部分放在不同的位置。
这是我失败的尝试。
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。例如,像这样的链接器脚本应该可以工作:
ENTRY(boot)
OUTPUT_FORMAT("binary")
SECTIONS {
. = 0x7c00;
.boot :
{
*(.boot)
}
. = 0x7dfe;
.sig : {
SHORT(0xaa55);
}
. = 0x8000;
.kernel : AT(0x7e00) /* place immediately after the boot sector */
{
*(.text)
*(.rodata)
*(.data)
_bss_start = .;
*(.bss)
*(COMMON)
_bss_end = .;
}
kernel_sectors = (SIZEOF(.kernel) + 511) / 512;
/DISCARD/ : {
*(.eh_frame)
}
}
我添加了一些内容来处理您将在 GCC 编译目标文件中看到的部分。 _bss_start
和 _bss_end
符号可用于将 .bss
部分归零,根据 Michael Petch 的建议,kernel_sector
符号设置为 512 字节扇区中内核的长度。
关于c - 如何通过将各自的部分放在不同的位置来链接两个目标文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52457734/