Подтвердить что ты не робот

Простое ядро ​​не загружается в GRUB

Я изучаю немного развития ОС от OSDev.org. У меня есть ядро, и я пытаюсь загрузить GRUB Legacy (0.97) с помощью qemu. Однако, когда я набираю kernel 200+9, я получаю сообщение

[Multiboot-elf, <0x100000:0x80:0x4008>(bad), entry=0x10000c]

Это то, что я ожидаю, за исключением (плохой) части. Если я наберу boot, теперь GRUB просто зависает.

Я думаю, что числа 0x100000, 0x44, 0x4008 обозначают начальный адрес сегмента .text, и начальный адрес .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

Итак, вы можете видеть, что числа, о которых я упоминал, почти совпадают. Проблема в том, что вместо 100044 начало .bss составляет всего 44. И я думаю, что именно по этой причине GRUB говорит плохо. У меня не может быть раздела ниже 1 МБ в памяти (низкая память). Но objdump говорит мне, что мои разделы выше этого порога, поэтому я не знаю, что случилось. Во всяком случае, я буду вставлять свой код ниже, он относительно короткий. Хотя мой вопрос, вероятно, очень прост, если раньше вы делали OS-dev, поэтому код может быть посторонним.

;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 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;
}

Ниже мой пользовательский компоновщик script:

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-байтным файлом (So stage1 + stage2 + pad имеют размер файла 102400 байт или 200 блоков, поэтому я загружаюсь с ядром 200 + 9).

Наконец, я запустил ядро ​​в qemu:

qemu-system-x86_64 -fda floppy.img
4b9b3361

Ответ 1

+1 для приятного вопроса со всеми подробностями, спасибо.

По крайней мере, на моей машине сгенерированный kernel.bin появляется как 4869 байт, который подходит только в 10 секторах, а не 9. Также текстовая память VGA находится в 0xb8000 not 0xb800 (еще один ноль - 0xb800 - сегмент реального режима, должен быть умножен на 16). С этими небольшими корректировками он отлично работает здесь.