为什么我的引导加载程序不加载我的内核?

Why doesn't my bootloader load my kernel?

我已经编写了 OS 在程序集上启动的最小实现:

    [BITS 16]
[ORG 0x7C00]
start:
mov ax, cs 
mov ds, ax  
mov ss, ax 
mov sp, start 

mov ax, 0x1100
mov es, ax
mov bx, 0x0000
mov dl, 1 
mov dh, 0 
mov ch, 0 
mov cl, 2 
mov al, 1 
mov ah, 0x02 
int 0x13 

mov ax, 0x1200
mov es, ax
mov bx, 0x0000
mov dl, 1
mov dh, 0
mov ch, 0
mov cl, 3
mov al, 1
mov ah, 0x02
int 0x13


cli
lgdt [gdt_info]
in al, 0x92
or al, 2
out 0x92, al    
mov eax, cr0
or al, 1
mov cr0, eax
jmp 0x8:protected_mode 
gdt:
db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
;base=0, size=4Gb, P=1, DPL=0, S=1(user),
;Type=1(code), Access=00A, G=1, B=32bit
db 0xff, 0xff, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00
;base=0, size=4Gb, P=1, DPL=0, S=1(user),
;Type=0(data), Access=0W0, G=1, B=32bit
db 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
gdt_info: 
dw gdt_info - gdt
dw gdt, 0
[BITS 32]
protected_mode:
mov ax, 0x10
mov es, ax
mov ds, ax
mov ss, ax
call 0x11000
times (512 - ($ - start) - 2) db 0 
db 0x55, 0xAA

以及 C 中内核的最小实现:

extern "C" int kmain();
__declspec(naked) void startup()
{
    __asm {
        call kmain;
    }
}
#define VIDEO_BUF_PTR (0xb8000)
void out_str(int color, const char* ptr, unsigned int strnum)
{
    unsigned char* video_buf = (unsigned char*)VIDEO_BUF_PTR;
    video_buf += 80 * 2 * strnum;
    while (*ptr)
    {
        video_buf[0] = (unsigned char)*ptr;
        video_buf[1] = color;
        video_buf += 2;
        ptr++;
    }
}
extern "C" int kmain()
{
    const char* hello = "Welcome to HelloWorldOS (gcc edition)!";
    out_str(0x07, hello, 0);
    while (1)
    {
        __asm hlt;
    }
    return 0;
}

使用 Microsoft C 编译器编译内核 引导转换器:Yasm 要从 PE 内核中获取数据,请使用 dumpbin 并获取:

Microsoft (R) COFF/PE Dumper Version 14.28.29335.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file kernel.bin

PE signature found

File Type: EXECUTABLE IMAGE

FILE HEADER VALUES
             14C machine (x86)
               2 number of sections
        604FC5B3 time date stamp Mon Mar 15 23:38:11 2021
               0 file pointer to symbol table
               0 number of symbols
              E0 size of optional header
             103 characteristics
                   Relocations stripped
                   Executable
                   32 bit word machine

OPTIONAL HEADER VALUES
             10B magic # (PE32)
           14.28 linker version
             200 size of code
             200 size of initialized data
               0 size of uninitialized data
            1000 entry point (00011000)
            1000 base of code
            2000 base of data
           10000 image base (00010000 to 00012FFF)
            1000 section alignment
             200 file alignment
            6.00 operating system version
            0.00 image version
            6.00 subsystem version
               0 Win32 version
            3000 size of image
             200 size of headers
             636 checksum
               1 subsystem (Native)
             500 DLL characteristics
                   NX compatible
                   No structured exception handler
          100000 size of stack reserve
            1000 size of stack commit
          100000 size of heap reserve
            1000 size of heap commit
               0 loader flags
              10 number of directories
               0 [       0] RVA [size] of Export Directory
               0 [       0] RVA [size] of Import Directory
               0 [       0] RVA [size] of Resource Directory
               0 [       0] RVA [size] of Exception Directory
               0 [       0] RVA [size] of Certificates Directory
               0 [       0] RVA [size] of Base Relocation Directory
            2044 [      1C] RVA [size] of Debug Directory
               0 [       0] RVA [size] of Architecture Directory
               0 [       0] RVA [size] of Global Pointer Directory
               0 [       0] RVA [size] of Thread Storage Directory
               0 [       0] RVA [size] of Load Configuration Directory
               0 [       0] RVA [size] of Bound Import Directory
               0 [       0] RVA [size] of Import Address Table Directory
               0 [       0] RVA [size] of Delay Import Directory
               0 [       0] RVA [size] of COM Descriptor Directory
               0 [       0] RVA [size] of Reserved Directory


SECTION HEADER #1
   .text name
      AE virtual size
    1000 virtual address (00011000 to 000110AD)
     200 size of raw data
     200 file pointer to raw data (00000200 to 000003FF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
60000020 flags
         Code
         Execute Read

SECTION HEADER #2
   .data name
      B0 virtual size
    2000 virtual address (00012000 to 000120AF)
     200 size of raw data
     400 file pointer to raw data (00000400 to 000005FF)
       0 file pointer to relocation table
       0 file pointer to line numbers
       0 number of relocations
       0 number of line numbers
C0000040 flags
         Initialized Data
         Read Write

  Debug Directories

        Time Type        Size      RVA  Pointer
    -------- ------- -------- -------- --------
    604FC5B3 coffgrp       50 00002060      460

  Summary

        1000 .data
        1000 .text

作为模拟器使用Qemu 结果我得到:

Booting from Hard disk...
Boot failed: could not read the boot disk

Booting from from Floppy...

仅此而已。那么为什么我的 OS 不起作用?我认为问题出在引导加载程序上,但我不确定。 (我才开始学习操作系统,所以我对它了解不多)。我必须运行满足我所有的条件

只需输入

qemu-system-x86_64 -boot order=ab -drive file=boot.BIN,format=raw,index=0,if=floppy -drive file=kernel.BIN,format=raw,index=1,if=floppy -L "C:\Program Files\qemu"

而不是

qemu-system-x86_64 -fda boot.BIN -fdb kernel.BIN -L "C:\Program Files\qemu"