NASM和clang/LLVM生成不同的对象文件



我正在尝试用multiboot制作一个简单的内核。我在NASM中使用了multiboot头,但现在我正试图用GNUAS语法重写它。我认为问题是clang(MacOS上的as(将多引导头放置在不同的地址(超过8K(,但我不知道如何让它像NASM一样工作。我使用的是相同的链接器脚本。

下面是我的NASM代码、GAS代码、链接器脚本和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

链接器脚本:

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=选项中可以看出,这台机器上的asclang,而不是GNU Binutils。ld.lld链接器也是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文档;如果无法识别节名称,则默认情况下该节不具有以上任何标志:它将不会在内存中分配,也不会写入,也不会执行。该部分将包含数据">

为了确保.boot节已加载到内存中并且可以由引导加载程序读取,该节必须添加"a"标志(更多信息请参阅上面的文档(。像这样:

// ... code ...

.section .multiboot_header, "a"
header_start:
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM
header_end:
// ... code ...

相关内容

  • 没有找到相关文章

最新更新