简单内核无法在 GRUB 中启动



我正在从OSDev.org学习一些操作系统开发。我有一个内核,我正在尝试使用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告诉我,我的section超过了阈值,我不知道哪里出了问题。无论如何,我将粘贴我的代码在下面,它相对较短。虽然我的问题可能是非常基本的,如果你以前做过操作系统开发,所以代码可能是无关的。

;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

+1,谢谢。

至少在我的机器上生成的kernel.bin是4869字节,只适合10个扇区而不是9个。此外,VGA文本内存位于0xb8000而不是0xb800(再多一个零- 0xb800是实模式段,必须乘以16)。通过这些小小的调整,它在这里工作得很好。

相关内容

  • 没有找到相关文章

最新更新