[英]NASM and clang/LLVM generating different object files
我正在尝试使用多重引导制作一个简单的 kernel。 我得到了在 NASM 中工作的 multiboot header,但现在我正试图用 GNU AS 语法重写它。 我认为问题是 clang ( as
在 MacOS 上)将多重引导 header 放置在不同的地址(超过 8K),但我不知道如何让它与 NASM 一样工作。 我正在使用相同的 linker 脚本。
下面是我的 NASM 代码、GAS 代码、linker 脚本和nm kernel-nasm.bin kernel-gas.bin
(抱歉,冗长)。
这是有效的 NASM 代码:
MBALIGN equ 1 << 0
MEMINFO equ 1 << 1
FLAGS equ MBALIGN | MEMINFO
MAGIC equ 0x1BADB002
CHECKSUM equ -(MAGIC + FLAGS)
section .multiboot_header
header_start:
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
header_end:
section .text
global start
start:
mov dword [0xb8000], 0x2f4b2f4f
hlt
这是不工作的 GNU AS 代码:
.set MBALIGN, 1 << 0
.set MEMINFO, 1 << 1
.set FLAGS, MBALIGN | MEMINFO
.set MAGIC, 0x1BADB002
.set CHECKSUM, -(MAGIC + FLAGS)
.section .multiboot_header
header_start:
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
header_end:
.section .text
.global start
start:
movl $0x2f4b2f4f, (0xb8000)
hlt
Linker 脚本:
ENTRY(start)
SECTIONS {
. = 1M;
.boot : ALIGN(4K)
{
/* ensure that the multiboot header is at the beginning */
*(.multiboot_header)
}
.text : ALIGN (4K)
{
*(.text)
}
}
nm kernel-nasm.bin kernel-gas.bin
:
kernel-nasm.bin:
e4524ffb a CHECKSUM
00000003 a FLAGS
1badb002 a MAGIC
00000001 a MBALIGN
00000002 a MEMINFO
0010000c r header_end
00100000 r header_start
00101000 T start
kernel-gas.bin:
e4524ffb a CHECKSUM
00000003 a FLAGS
1badb002 a MAGIC
00000001 a MBALIGN
00000002 a MEMINFO
0000000c n header_end
00000000 n header_start
00100000 T start
这是我用来组装代码的命令。 我在 macOS 上使用 Homebrew 的 LLVM 14.0.6:
# For kernel-nasm.bin
nasm -felf32 kernel-nasm.asm -o kernel-nasm.o
ld.lld -n -o kernel-nasm.bin -T linker.ld kernel-nasm.o
# For kernel-gas.bin
as --target=i386-pc-none-elf kernel-gas.S -o kernel-gas.o
ld.lld -n -o kernel-gas.bin -T linker.ld kernel-gas.o
从--target=
选项可以看出as
在这台机器上是clang
,而不是来自 GNU Binutils。 ld.lld
linker 相同,它是 LLVM,而不是 Binutils。
objdump -x kernel-nasm.bin
是:
kernel-nasm.bin: file format elf32-i386
kernel-nasm.bin
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00101000
Program Header:
LOAD off 0x00001000 vaddr 0x00100000 paddr 0x00100000 align 2**12
filesz 0x0000000c memsz 0x0000000c flags r--
LOAD off 0x00002000 vaddr 0x00101000 paddr 0x00101000 align 2**12
filesz 0x0000000b memsz 0x0000000b flags r-x
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**0
filesz 0x00000000 memsz 0x00000000 flags rw-
Sections:
Idx Name Size VMA LMA File off Algn
0 .boot 0000000c 00100000 00100000 00001000 2**12
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .text 0000000b 00101000 00101000 00002000 2**12
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .comment 0000001c 00000000 00000000 0000200b 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00000000 l df *ABS* 00000000 hdr.asm
00000001 l *ABS* 00000000 MBALIGN
00000002 l *ABS* 00000000 MEMINFO
00000003 l *ABS* 00000000 FLAGS
1badb002 l *ABS* 00000000 MAGIC
e4524ffb l *ABS* 00000000 CHECKSUM
00100000 l .boot 00000000 header_start
0010000c l .boot 00000000 header_end
00101000 g .text 00000000 start
objdump -x kernel-gas.bin
为:
kernel-gas.bin: file format elf32-i386
kernel-gas.bin
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00100000
Program Header:
LOAD off 0x00001000 vaddr 0x00100000 paddr 0x00100000 align 2**12
filesz 0x0000000b memsz 0x0000000b flags r-x
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**0
filesz 0x00000000 memsz 0x00000000 flags rw-
Sections:
Idx Name Size VMA LMA File off Algn
0 .boot 0000000c 00000000 00000000 00002000 2**12
CONTENTS, READONLY
1 .comment 0000001c 00000000 00000000 0000200c 2**0
CONTENTS, READONLY
2 .text 0000000b 00100000 00100000 00001000 2**12
CONTENTS, ALLOC, LOAD, READONLY, CODE
SYMBOL TABLE:
e4524ffb l *ABS* 00000000 CHECKSUM
00000003 l *ABS* 00000000 FLAGS
1badb002 l *ABS* 00000000 MAGIC
00000001 l *ABS* 00000000 MBALIGN
00000002 l *ABS* 00000000 MEMINFO
0000000c l .boot 00000000 header_end
00000000 l .boot 00000000 header_start
00100000 g .text 00000000 start
根据GNU AS 文档,“如果无法识别节名称,则默认情况下该节没有上述标志:它不会在 memory 中分配,也不能写,也不能执行。该节将包含数据。”
为了确保.boot
部分被加载到 memory 并且可以被引导加载程序读取,该部分必须添加"a"
标志(更多信息在上面的文档中)。 像这样:
// ... code ...
.section .multiboot_header, "a"
header_start:
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
header_end:
// ... code ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.