标准MinGW/32LD链接器不输出ELF二进制文件。您最好使用 i686 交叉编译器,但如果您不使用,您也许可以摆脱下面的提示。
看来您正在使用 Arjun 的让我们写一个内核 http://arjunsreedharan.org/post/82710718100/kernel-101-lets-write-a-kernel教程。如果您正在遵循该教程,那么您错过了一个步骤kernel.asm
兼容于GRUB引导加载程序和QEMU's -kernel
选项。在我们开始之前,您应该阅读本教程的其余部分。以下代码将 Multiboot 标头添加到kernel.asm
使其与 GRUB 兼容:
;;kernel.asm
bits 32 ;nasm directive - 32 bit
global entry
extern _kmain ;kmain is defined in the c file
section .text
entry: jmp start
;multiboot spec
align 4
dd 0x1BADB002 ;magic
dd 0x00 ;flags
dd -(0x1BADB002 + 0x00) ;checksum. m+f+c should be zero
start:
cli ;block interrupts
mov esp, stack_space ;set stack pointer
call _kmain
hlt ;halt the CPU
section .bss
resb 8192 ;8KB for stack
stack_space:
除了添加标题之外,我还添加了entry
文件中的标签和jmp start
跳过多重引导标头。我这样做是为了方便您将来开始调试时在 0x100000 处设置断点。
另一项变化是在 MinGW 上,GCC默认情况下为函数名称添加下划线。我已经更改了对C功能kmain
to _kmain
。这与 Linux 约定不同。
由于我们代码的入口点现在是entry
代替start
我已经修改了link.ld
to be:
/*
* link.ld
*/
OUTPUT_FORMAT(pei-i386)
ENTRY(entry)
SECTIONS
{
. = 0x100000;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
上面文件中的另一个重要变化是使用OUTPUT_FORMAT(pei-i386)
。这将输出一个可移植可执行映像(32 位)而不是ELF(不支持)。
为了构建内核并生成ELF图像来自PEI-I386我们可以使用这些命令:
nasm -f elf32 kernel.asm -o kasm.o
gcc -m32 -c kernel.c -o kc.o -ffreestanding -nostdlib -nostdinc
ld -T link.ld -o kernel kasm.o kc.o -build-id=none
objcopy -O elf32-i386 kernel kernel.elf
The LD命令已修改为不将 build-id 写入可执行文件,以避免多重引导标头移至可执行文件的前 8k 之外。这GCC选项已被修改为使用选项生成独立代码(没有标准库和包含)-ffreestanding -nostdlib -nostdinc
。我们用objcopy
来转换PEI-I386 file (kernel
) to an ELF32图像称为kernel.elf
。你会想要使用kernel.elf
with GRUB and/or QEMU.