“必须先加载内核”

时间:2018-12-03 17:03:17

标签: c assembly kernel bootloader

我写了一个迷你引导程序和一个简单的内核来打印字符串。我逐步进行了this playlist(准确地说是前3个视频!)。无论如何,当我启动虚拟机(使用ISO)时,会收到以下消息:

“错误:找不到多重引导头。”

“错误:您需要先加载内核。”

我试图在启动文件中修改汇编代码的某些部分,但没有成功。

代码如下:

boot.s

.set MAGIC, 0x1badb002
.set FLAGS, (1<<0 | 1<<1)
.set CHECKSUM, -(MAGIC + FLAGS)

.section .multiboot
    .long MAGIC
    .long FLAGS
    .long CHECKSUM

.section .text
.extern kernel_main
.extern call_constructors
.global loader

loader:
    mov $kernel_stack, %esp
    call call_constructors
    push %eax
    push %ebx
    call kernel_main

_stop:
    cli
    hlt
    jmp _stop


.section .bss
.space 2*1024*1024 ;#2 MiB
kernel_stack:   

kernel.c

#include <sys/types.h>

void printf(char * str)
{
    uint16_t * VideoMemory = (uint16_t *)0xb8000;
    for(int32_t i = 0; str[i] != '\0'; i++)
        VideoMemory[i] = (VideoMemory[i] & 0xFF00) | str[i];
}

typedef void (*constructor)();
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" void call_constructors()
{
    for(constructor* i = &start_ctors; i != &end_ctors; i++)
        (*i)();
}

extern "C" void kernel_main(const void * multiboot_structure, uint32_t magic_number)
{
    printf("Denos - Version: 0.0.1a");
    for(;;);
}

注意:sys / types.h来自我的lib。包含在gcc中作为参数。

linker.ld

ENTRY(loader)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:i386)

SECTIONS
{
    . = 0x0100000;
    .text :
    {
        *(.multiboot)
        *(.text*)
        *(.rodata)
    }

    .data :
    {
        start_ctors = .;
        KEEP(*( .init_array ));
        KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
        end_ctors = .;
        *(.data)
    }

    .bss :
    {
        *(.bss)
    }

    /DISCARD/ :
    {
        *(.fini_array*)
        *(.comment)
    }
}

Makefile

GPPPARAMS = -m32 -fno-use-cxa-atexit -nostdlib -fno-builtin -fno-rtti         -fno-exceptions -fno-leading-underscore -I ../include/
ASPARAMS = --32
objects = boot.o kernel.o

run: denos.iso
    (killall VirtualBox && sleep 1) || true
    VirtualBox --startvm 'denos' &

%.o: %.c
    gcc $(GPPPARAMS) -o $@ -c $<

%.o: %.s
    as $(ASPARAMS) -o $@ $<

kernel.bin : linker.ld $(objects)
    ld $(LDPARAMS) -T $< -o $@ $(objects)

install: kernel.bin
    sudo cp $< ./boot/kernel.bin

denos.iso: kernel.bin
    mkdir iso
    mkdir iso/boot
    mkdir iso/boot/grub
    cp kernel.bin iso/boot/kernel.bin
    echo 'set timeout=0'                        > iso/boot/grub/grub.cfg
    echo 'set default=0'                        >> iso/boot/grub/grub.cfg
    echo ''                                     >> iso/boot/grub/grub.cfg
    echo 'menuentry "Denos" {'                  >> iso/boot/grub/grub.cfg
    echo '  multiboot /boot/kernel.bin'         >> iso/boot/grub/grub.cfg
    echo '  boot'                               >> iso/boot/grub/grub.cfg
    echo '}'                                    >> iso/boot/grub/grub.cfg
    grub-mkrescue --output=denos.iso iso
    rm -rf iso
    mv -f denos.iso /home/data/libvirt_iso/

objdump -x kernel.bin (已请求)

kernel.bin:     file format elf32-i386
kernel.bin
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x0010000c

Program Header:
    LOAD off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**21
        filesz 0x001001ac memsz 0x003001ac flags rwx
   STACK off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**4
        filesz 0x00000000 memsz 0x00000000 flags rwx

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00000100  00100000  00100000  00100000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .eh_frame     000000a0  00100100  00100100  00100100  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .got.plt      0000000c  001001a0  001001a0  001001a0  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  3 .bss          00200000  001001ac  001001ac  001001ac  2**0
                  ALLOC
SYMBOL TABLE:
00100000 l    d  .text  00000000 .text
00100100 l    d  .eh_frame  00000000 .eh_frame
001001a0 l    d  .got.plt   00000000 .got.plt
001001ac l    d  .bss   00000000 .bss
00000000 l    df *ABS*  00000000 boot.o
1badb002 l       *ABS*  00000000 MAGIC
00000003 l       *ABS*  00000000 FLAGS
e4524ffb l       *ABS*  00000000 CHECKSUM
003001ac l       .bss   00000000 kernel_stack
0010001d l       .text  00000000 _stop
00000000 l    df *ABS*  00000000 kernel.c
00000000 l    df *ABS*  00000000 
001001a0 l     O .got.plt   00000000 _GLOBAL_OFFSET_TABLE_
001001a0 g       .got.plt   00000000 start_ctors
001000e0 g     F .text  00000000 .hidden __x86.get_pc_thunk.ax
001000c2 g     F .text  0000001e kernel_main
001000e4 g     F .text  00000000 .hidden __x86.get_pc_thunk.bx
001001a0 g       .got.plt   00000000 end_ctors
00100088 g     F .text  0000003a call_constructors
00100021 g     F .text  00000067 _Z6printfPc
0010000c g       .text  00000000 loader

1 个答案:

答案 0 :(得分:2)

对不起,我浪费了别人几次。我检查了“ Makefile”文件,发现自己丢失了“ LDPARAMS = -melf_i386”。现在启动并打印 还是谢谢。