OSDev.orgから OS 開発について少し学んでいます。カーネルがあり、qemu を使用して GRUB Legacy (0.97) で起動しようとしています。ただし、入力するとkernel 200+9
、メッセージが表示されます
[Multiboot-elf, <0x100000:0x80:0x4008>(bad), entry=0x10000c]
これは、(悪い)部分を除いて、私が期待するものです。ここで入力するboot
と、GRUB がハングします。
0x100000、0x44、0x4008 という数字は、それぞれ .text セグメントの開始アドレス、.bss の開始アドレス、.bss セクションのサイズを表していると思います。objdump -h
これは、カーネル イメージで実行すると次の出力が得られるためだと思います。
kernel.bin: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000044 00100000 00100000 00001000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .bss 00004008 00100044 00100044 00001044 2**2
ALLOC
先ほど挙げた数字がほぼ一致していることがわかります。問題は、.bss の開始が 100044 ではなく 44 になっていることです。これが、GRUB が悪いと言っている理由だと思います。メモリ内に 1 MB 未満のセクションを作成できません (メモリ不足)。しかし、objdump は、セクションがそのしきい値を超えていることを示しているため、何が問題なのかわかりません。とにかく、コードを下に貼り付けます。比較的短いです。以前にOS開発を行ったことがある場合、私の質問はおそらく非常に基本的なものなので、コードは無関係かもしれません。
;loader.s - contains the multiboot header for grub and calls the main kernel method
global loader ; making entry point visible to linker
global magic ; we will use this in kmain
global mbd ; we will use this in kmain
extern kmain ; kmain is defined in kmain.cpp
; setting up the Multiboot header - see GRUB docs for details
MODULEALIGN equ 1<<0 ; align loaded modules on page boundaries
MEMINFO equ 1<<1 ; provide memory map
FLAGS equ 0x03;MODULEALIGN | MEMINFO ; this is the Multiboot 'flag' field
MAGIC equ 0x1BADB002 ; 'magic number' lets bootloader find the header
CHECKSUM equ -(MAGIC + FLAGS) ; checksum required
section .text
loader:
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
; reserve initial kernel stack space
STACKSIZE equ 0x4000 ; that's 16k.
mov esp, stack + STACKSIZE ; set up the stack
mov [magic], eax ; Multiboot magic number
mov [mbd], ebx ; Multiboot info structure
call kmain ; call kernel proper
cli
.hang:
hlt ; halt machine should kernel return
jmp .hang
section .bss
align 4
stack: resb STACKSIZE ; reserve 16k stack on a doubleword boundary
magic: resd 1
mbd: resd 1
.
// kernel.c - Contains the main kernel method
void kmain() {
extern unsigned int magic;
if (magic != 0x2BADB002) {
// Something went wrong
}
volatile unsigned char *videoram = (unsigned char *) 0xB800;
videoram[0] = 65;
videoram[1] = 0x07;
}
以下は、私のカスタム リンカー スクリプトです。
ENTRY (loader)
SECTIONS {
. = 0x00100000;
.text ALIGN (0x1000) : {
*(.text)
}
.rodata ALIGN (0x1000) :
{
*(.rodata*)
}
.data ALIGN (0x1000) :
{
*(.data)
}
.bss :
{
sbss = .;
*(COMMON)
*(.bss)
ebss = .;
}
/DISCARD/ : {
*(.eh_frame)
*(.comment)
}
}
最後に、次の行でカーネルをビルドします。
nasm -f elf -o loader.o loader.s
gcc -c -o kernel.o kernel.c
ld -T linker.ld -o kernel.bin loader.o kernel.o
cat stage1 stage2 pad kernel.bin > floppy.img
stage1 と stage2 は GRUB Legacy のファイルで、pad は任意の 750 バイトのファイルです (つまり、stage1+stage2+pad のファイル サイズは 102400 バイト、つまり 200 ブロックです。これが、カーネル 200+9 で起動する理由です)。
最後に、qemu でカーネルを実行します。
qemu-system-x86_64 -fda floppy.img