Linux “错误”;找不到多引导标头“;当我试图编译自己的操作系统时

Linux “错误”;找不到多引导标头“;当我试图编译自己的操作系统时,linux,gcc,assembly,x86,osdev,Linux,Gcc,Assembly,X86,Osdev,我已经用c编写了一个带有程序集引导加载程序的裸体操作系统,但我无法让它运行,每次运行它时,我都会从grub2中得到错误“找不到多引导头”。我知道我的代码不是问题所在,我曾尝试编译其他操作系统,但它们给出了相同的错误。系统规格:Ubuntu Linux和gcc版本7.2。我已经看了所有其他关于这个的问题,没有一个对我有用 我正在使用以下命令编译我的操作系统: as boot.s -o boot.o gcc -c kernel.c -o kernel.o -std=gnu99 -ffreestan

我已经用c编写了一个带有程序集引导加载程序的裸体操作系统,但我无法让它运行,每次运行它时,我都会从grub2中得到错误“找不到多引导头”。我知道我的代码不是问题所在,我曾尝试编译其他操作系统,但它们给出了相同的错误。系统规格:Ubuntu Linux和gcc版本7.2。我已经看了所有其他关于这个的问题,没有一个对我有用

我正在使用以下命令编译我的操作系统:

as boot.s -o boot.o

gcc -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra

gcc -T linker.ld -o MyOS.bin -ffreestanding -O2 -nostdlib kernel.o boot.o -lgcc

grub-file --is-x86-multiboot MyOS.bin

mkdir -p isodir/boot/grub
cp MyOS.bin isodir/boot/MyOS.bin
cp grub.cfg isodir/boot/grub/grub.cfg
grub-mkrescue -o MyOS.iso isodir

qemu-system-x86_64 -cdrom MyOS.iso
引导加载程序:

    # set magic number to 0x1BADB002 to identified by bootloader   
.set MAGIC,    0x1BADB002  

# set flags to 0  
.set FLAGS,    0  

# set the checksum  
.set CHECKSUM, -(MAGIC + FLAGS)  

# set multiboot enabled  
.section .multiboot  

# define type to long for each data defined as above  
.long MAGIC  
.long FLAGS  
.long CHECKSUM  


# set the stack bottom   
stackBottom:  

# define the maximum size of stack to 512 bytes  
.skip 512  


# set the stack top which grows from higher to lower  
stackTop:  

.section .text  
.global _start  
.type _start, @function  


_start:  

  # assign current stack pointer location to stackTop  
    mov $stackTop, %esp  

  # call the kernel main source  
    call KERNEL_MAIN  

    cli  


# put system in infinite loop  
hltLoop:  

    hlt  
    jmp hltLoop  

.size _start, . - _start  
链接器:

/* The bootloader will look at this image and start execution at the symbol designated at the entry point. */
ENTRY(_start)

SECTIONS
{
    /* Begin putting sections at 1 MiB, a conventional place for kernels to be
       loaded at by the bootloader. */
    . = 1M;

    /* First put the multiboot header, as it is required to be put very early in the image or the bootloader won't recognize the file format. Next we'll put the .text section. */
    .text BLOCK(4K) : ALIGN(4K)
    {
        *(.multiboot)
        *(.text)
    }

    /* Read-only data. */
    .rodata BLOCK(4K) : ALIGN(4K)
    {
        *(.rodata)
    }

    /* Read-write data (initialized) */
    .data BLOCK(4K) : ALIGN(4K)
    {
        *(.data)
    }

    /* Read-write data (uninitialized) and stack */
    .bss BLOCK(4K) : ALIGN(4K)
    {
        *(COMMON)
        *(.bss)
        *(.bootstrap_stack)
    }
}
内核:

#include"kernel.h"  

static UINT16 VGA_DefaultEntry(unsigned char to_print) {  
    return (UINT16) to_print | (UINT16)WHITE_COLOR << 8;  
}  

void KERNEL_MAIN()  
{  
  TERMINAL_BUFFER = (UINT16*) VGA_ADDRESS;  

  TERMINAL_BUFFER[0] = VGA_DefaultEntry('H');  
  TERMINAL_BUFFER[1] = VGA_DefaultEntry('e');  
  TERMINAL_BUFFER[2] = VGA_DefaultEntry('l');  
  TERMINAL_BUFFER[3] = VGA_DefaultEntry('l');  
  TERMINAL_BUFFER[4] = VGA_DefaultEntry('o');  
  TERMINAL_BUFFER[5] = VGA_DefaultEntry(' ');  
  TERMINAL_BUFFER[6] = VGA_DefaultEntry('W');  
  TERMINAL_BUFFER[7] = VGA_DefaultEntry('o');  
  TERMINAL_BUFFER[8] = VGA_DefaultEntry('r');  
  TERMINAL_BUFFER[9] = VGA_DefaultEntry('l');  
  TERMINAL_BUFFER[10] = VGA_DefaultEntry('d');  
}  
#包括“kernel.h”
静态UINT16 VGA_默认项(未签名字符到_打印){

将(UINT16)返回到|打印|(UINT16)白色|确保您有一个链接器脚本,将多boode头放在顶部(它需要位于您生成的ELF可执行文件的前8kb中,并在4字节边界上对齐)。如果使用64位GCC编译器(最好使用i686或i385交叉编译器)然后您需要链接到
-z max page size=4096
(我假设您链接的是GCC)如果创建32位内核,请使用
-m32
。如果您向我们展示了链接器脚本、多重启动程序集文件以及用于链接和编译的命令,这会有所帮助。请展示用于编译自定义加载程序的命令,以及如何链接二进制文件。您可能需要展示您编写的代码。我的最佳猜测来自您发布的内容是,您正在将32位内核编译为64位程序。在GCC命令行上使用
-m32
进行编译和链接。这是一个猜测,因为您实际上没有向我们显示
boot.s
好的,现在向我们显示您的
linker.ld
。显示链接器脚本也很重要,因此我们知道
。multiboot
部分放在第一位。您可能需要做的另一件事是在GCC链接器命令行上指定
-Wl,--build id=none
-N
,感谢您发布这些文件。现在在我上面的评论中,首先向所有GCC命令添加
-m32
,以强制进行32位编译(因为您目前正在编写32位内核)。使用
as
命令,您必须添加
--32
。在执行链接的GCC行上,还添加
-Wl,--build id=none