繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM