24

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
4

1 に答える 1

24

すべての詳細を含む素敵な質問のために+1、ありがとう。

少なくとも私のマシンでは、生成さkernel.binれたものは4869バイトであり、9ではなく10セクターにしか収まりません。また、VGAテキストメモリはそうでは0xb8000ありません0xb800(もう1つのゼロ-0xb800リアルモードセグメントであり、16を掛ける必要があります)。これらの小さな調整で、ここでうまく機能します。

于 2013-01-14T15:05:28.620 に答える