【发布时间】:2021-12-04 16:12:43
【问题描述】:
我有kernel.c 文件看起来像这样
void main() {
char *video_memory = (char *)0xb8000;
*video_memory = 'X';
}
我用这两个命令编译和链接:
gcc -ffreestanding -c ./src/kernel/kernel.c -o kernel.o -m32 -mtune=i386 -fno-pie
ld -o kernel.bin -Ttext=0x1000 kernel.o --oformat binary -m elf_i386 --strip-all -nmagic
它产生了一个 128MB 的 kernel.bin
但是,当我在 ld 命令中删除 -Ttext=0x1000 时,它会生成一个 120B 的 kernel.bin。
如果我理解正确,-Ttext=0x1000 会将偏移量0x1000 添加到所有内存引用。为什么会有这么大的不同?
【问题讨论】:
-
如果您选择不同的输出格式,例如默认的 ELF,它会为带有
-Ttext=0x1000的各个部分或段选择什么地址? (使用readelf -a)。我猜有两件事相距甚远,而一个扁平的二进制文件只是用零填充以填补空白。是的,我试过了,0x080480d4有一个只读的非执行段(从 0x1000 大约 128MiB),持有.note.gnu.property部分。 -
IDK 如何摆脱它,否则我会将其发布为答案,但请查看手册;链接器脚本可以工作,但也许是一种过滤部分的方法。
-
非常感谢您的回复。将此添加到链接器脚本将完成工作
/DISCARD/ : { *(.note.gnu.property) } -
首先不要构建到二进制,构建到精灵。然后使用 readelf 或 objdump 或其他来显示可加载部分的位置。如果你有一个在 0x00000000 并且它有 1 个字节和一个在 0x1000000 并且它有一个字节,那么它将填充 0x0FFFFFF 字节并创建一个 0x10000001 字节文件。但是,如果你在 0x10000000 有一个东西,在 0x10001000 有一个字节,那么它将生成一个 0x1001 字节的文件,其中包含所需的任何填充。 -O 二进制文件(objcopy)必须从段的最低地址开始,并填充并填充到最高地址。创建输出
标签: assembly gcc linker operating-system ld