我正在尝试用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=
选项中可以看出,这台机器上的as
是clang
,而不是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 ...