与 ld 链接的引导扇区具有 QEMU 打印"Hard Disk Boot Failed: not a bootable disk"



我和几个朋友正在做一个非常简单的内核项目。目前,我们有一个引导加载程序(使用GNU汇编(和一个简单的内核(没有stdlib的C(。我的任务是建立一个QEMU模拟来测试操作系统,但在这个过程中遇到了几个问题。

我已经启动了QEMU,并创建了一个可启动的磁盘映像。

Makefile:

%.o: %.S
as -o $@ -c $<
bootsect: boot.o
ld -o ./bin/bootsect.bin $^ -nostdlib -Ttext 0x7C00
img: bootsect
dd if=/dev/zero of=boot.img bs=512 count=2880
dd if=./bin/bootsect.bin of=boot.img conv=notrunc bs=512 count=1

我试着用qemu-system-i386 -drive format=raw,file=boot.img运行它我也尝试过各种方法来引导图像,但最终总是出现相同的错误:

Booting from Hard Disk:
Boot failed: not a bootable disk

如果需要,下面是引导加载程序代码:

.code16
.org 0
.text
.global _start
_start:
cli
xorw %ax, %ax
movw %ax, %es
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw $0x3000, %sp
sti
movw $hello, %si
call print
print:
xorb %bh, %bh
movb $0x0E, %ah
lodsb
cmpb $0, %al
je 1f
int $0x10;
jmp print
1:
ret
hello:
.asciz "HELLO WORLDn"
.org 510
.word 0xAA55

问题出在哪里?

链接器正在创建一个ELF可执行文件,而不是原始二进制文件。您需要将.text部分中包含的原始代码提取到一个独立的文件中,而不需要任何包装对象代码格式。只有这样,您才能将该文件拼接到磁盘映像中作为引导扇区。

有两种方法可以做到这一点。一种是在Makefile中添加一个额外的步骤,调用objcopy:

bootsect: bin/bootsect.bin
bin/bootsect.elf: boot.o
ld -o $@ $^ -nostdlib -Ttext=0x7c00
%.bin: %.elf
objcopy -Obinary -j.text $< $@

另一种是使用链接器脚本。将以下内容放入名为bootsect.ld:的文件中

OUTPUT_FORMAT("binary")
SECTIONS {
.image 0x7c00 : {
*(.text)
}
}

在Makefile中:

bin/bootsect.bin: boot.o bootsect.ld
ld -o $@ boot.o -nostdlib -Tbootsect.ld

要检查这是否有效,请运行file bin/bootsect.bin。它应该输出"DOS/MBR引导扇区"。

最新更新