2013-01-14 17 views
23

Uczę się trochę rozwoju systemu operacyjnego od OSDev.org. Mam jądro i próbuję uruchomić system w GRUB Legacy (0.97) używając qemu. Jednak, gdy wpisuję kernel 200+9, otrzymuję komunikatProste jądro nie uruchomi się w GRUB

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

To jest to, czego oczekuję wyjątkiem części (złe). Jeśli piszę teraz: boot, teraz GRUB po prostu się zawiesza.

Myślę, że numery 0x100000, 0x44, 0x4008 oznaczają odpowiednio adres początkowy segmentu .tekst, adres początkowy .bss i rozmiar sekcji .bss. Myślę, że to dlatego, że działa objdump -h na obrazie jądra daje to wyjście:

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 

dzięki czemu można zobaczyć, że numery I wspomniał prawie dopasować. Problem polega na tym, że zamiast 100044, początek .bss wynosi zaledwie 44. I myślę, że właśnie dlatego GRUB mówi źle. Nie mogę mieć sekcji poniżej 1 MB w pamięci (mała pamięć). Ale objdump mówi mi, że moje sekcje są powyżej tego progu, więc nie wiem, co jest nie tak. W każdym razie wkleję poniższy kod, jest on stosunkowo krótki. Chociaż moje pytanie jest prawdopodobnie bardzo proste, jeśli wcześniej tworzyłeś OS-a, więc kod może być nieistotny.

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

Poniżej jest mój skrypt niestandardowy łącznik:

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

I wreszcie zbudować jądro z następującymi liniami:

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 

Gdzie stage1 i stage2 jest plik z GRUB Legacy i pad jest plikiem o wielkości 750 bajtów (więc stage1 + stage2 + pad ma rozmiar pliku 102400 bajtów, czyli 200 bloków, dlatego uruchamiam jądrem 200 + 9).

Wreszcie uruchomić jądro w qemu:

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

Repository z tego przykładu roboczego: https://github.com/cirosantilli/x86-bare-metal-examples/tree/d217b180be4220a0b4a453f31275d38e697a99e0/multiboot/osdev –

Odpowiedz

22

+1 dla miłej pytanie ze wszystkimi szczegółami, dziękuję.

Przynajmniej na moim komputerze generowane kernel.bin wychodzi jako 4869 bajtów, który pasuje tylko w 10 sektorach nie 9. Ponadto, pamięć tekst VGA na 0xb8000 nie 0xb800 (jeden bardziej Zero - 0xb800 jest segment w trybie rzeczywistym, należy pomnożyć przez 16). Dzięki tym małym zmianom działa tutaj dobrze.

+0

Wow, problem był z 0xb800 ... Myślałem, że to wisi ale tak naprawdę to nie było umieszczanie postaci we właściwym miejscu w pamięci ... Chociaż nadal nie rozumiem, co to znaczyło: '<0x100000: 0x80: 0x4008> (zły)', ponieważ nie powinieneś być może mieć segment w niskiej pamięci (jeśli poprawnie odczytałem znaczenie liczb) ... – gsingh2011

+0

I dla wyjaśnienia nieco innym, nadal działa, mimo że mówi (zły). – gsingh2011

+2

Mówi '(zły)' jeśli nie ładujesz wystarczającej liczby sektorów. Może nadal działać, jeśli w tej części nie ma nic ważnego. Czy próbowałeś z '200 + 10'? – Jester

Powiązane problemy