Assembly GNU作为值不在分配的节中
我目前正试图在GNU汇编程序中构建一个两阶段引导加载程序。我使用Assembly GNU作为值不在分配的节中,assembly,x86-16,bootloader,gnu-assembler,linker-scripts,Assembly,X86 16,Bootloader,Gnu Assembler,Linker Scripts,我目前正试图在GNU汇编程序中构建一个两阶段引导加载程序。我使用as命令编译汇编文件,使用ld命令将它们链接到最终的二进制文件。事先提供一些信息: $ as --version GNU assembler (GNU Binutils for Debian) 2.28 [...] This assembler was configured for a target of `x86_64-linux-gnu' 和ld: $ ld --version GNU ld (GNU Binutils for
as
命令编译汇编文件,使用ld
命令将它们链接到最终的二进制文件。事先提供一些信息:
$ as --version
GNU assembler (GNU Binutils for Debian) 2.28 [...]
This assembler was configured for a target of `x86_64-linux-gnu'
和ld
:
$ ld --version
GNU ld (GNU Binutils for Debian) 2.28 [...]
受影响的程序集文件:
.code16
.section .test
label: .short 0x1234
.section .text
.global _setup32
_setup32:
cli
xor %ax, %ax
# Some more code [...]
以及用于构建二进制文件的链接器脚本:在任何人询问之前,以下链接器脚本是我的引导加载程序的第2阶段部分,因此是0x8000
的起源
OUTPUT_FORMAT(binary)
ENTRY(_setup32)
SECTIONS
{
. = 0x8000;
_SETUP_START = .;
.test ALIGN(0x10) : {
*(.test*)
}
.text ALIGN(0x10) : {
_TEXT_START = .;
*(.text*)
_TEXT_END = .;
}
.rodata ALIGN(0x10) : {
_RODATA_START = .;
*(.rodata*)
_RODATA_END = .;
}
.data ALIGN(0x10) : {
_DATA_START = .;
*(.data*)
_DATA_END = .;
}
.bss ALIGN(0x10) : {
_BSS_START = .;
*(.bss*)
_BSS_END = .;
}
/DISCARD/ : {
*(.comment*)
}
_SETUP_END = .;
}
但是,在生成最终的setup.bin
文件后,值0x1234
不位于hextump的开头。事实上,它甚至没有包含在最终构建中。引导加载程序工作得非常好,我只是无法将变量或一般情况下的字节分配给各个部分
我在Makefile中使用以下非常基本的规则:
$(SETUPBIN): $(SETUP).o
$(LD) -T setup.ld $(SETUP).o -o $@
%.o: %.asm
$(AS) $< -o $@
$(SETUPBIN):$(SETUP).o
$(LD)-T setup.LD$(setup).o-o$@
%.o:%.asm
$(AS)$<-o$@
此外:我知道GNU是作为指令.text
和.data
,但它们只在二进制文件的固定位置存储指令和字节:.text
指令中的所有内容都位于二进制文件的开头,而.data
中的所有内容都位于二进制文件的末尾
如何将所有内容放在自定义分区中?x86是little endian。您确实检查了字节序列
0x34 0x12
,对吗?我不确定您是否需要执行链接器脚本之外的任何特殊操作,以便在输出二进制文件中显示自定义部分。(例如,对于ELF输出,您需要一个“@progbits”
属性来获取放置在将要映射的段中的节,但在平面二进制中,除.bss之外的所有节都仅在二进制中。)@PeterCordes正确。但在平面二进制文件中找不到该值。我也很想知道,输出是否只是针对平面二进制文件进行了一些裁剪或优化,但我也没有发现这方面的任何内容。您需要使用.section.test,“a”
将其标记为可分配。@Jester非常感谢,这非常有效!