2013-01-14 36 views
23

我正在从OSDev.org那里学习一点操作系统开发。我有一个内核,我试图使用qemu在GRUB Legacy(0.97)中启动。但是,当我输入kernel 200+9,我得到的消息简单的内核在GRUB中无法启动

[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 

所以你可以看到,这些数字我提到几乎匹配。问题是,而不是100044,.bss的开始只是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旧版文件pad是任何750字节文件(因此stage1 + stage2 + pad的文件大小为102400字节,或200个块,这就是为什么我使用内核200 + 9启动的原因)。

最后,我在QEMU运行的内核:

qemu-system-x86_64 -fda floppy.img 
+0

库与例如工作:https://github.com/cirosantilli/x86-bare-metal-examples/tree/d217b180be4220a0b4a453f31275d38e697a99e0/multiboot/osdev –

回答

22

+1的所有细节有趣的问题,谢谢。

至少我的机器所生成的kernel.bin出来作为4869个字节,其中仅装配在10个扇区不9.另外,VGA文本存储器在0xb80000xb800(一个多个零 - 0xb800是实模式的段,必须乘以16)。通过这些小小的调整,它在这里运行得很好

+0

哇,这个问题是与0xb800 ...我想这是挂但它确实不会将角色放在内存中的正确位置上......虽然我仍然对这意味着什么感到困惑:'0x100000:0x80:0x4008>(bad)',因为你不应该允许在低内存中有段(如果我正确地解释了数字的含义)... – gsingh2011

+0

为了澄清其他人,它仍然会启动,即使它说(坏)。 – gsingh2011

+2

它说'(坏)'如果你没有加载足够的扇区。如果在那部分中没有重要的东西,它可能仍然有效。你用'200 + 10'试过了吗? – Jester