如何在 C 中正确创建内核并将 link 引导加载程序

How to properly create a kernel in C and link to bootloader

我在这里组装了一个简单的引导加载程序:

;initialization type stuff
[bits 16]
[org 0x7c00]

;make message and print it
mov si, MESSAGE
call print

;infinite loop to stall
jmp $

;print "method"
print:
    pusha
    print_loop:
        mov al, [si]
        cmp al, 0
        jne print_char
        popa
        ret
    print_char:
        mov ah, 0x0e
        int 0x10
        add si, 1
        jmp print_loop

;actual assigning of message
MESSAGE: db "Hello World!", 0

;padding & magic number (end)
times 510-($-$$) db 0
dw 0xaa55

我的目标是用 C 编写大部分 OS,目前我正尝试在 C:link 中正确地 link 引导加载程序和内核:

void kernel_main()
{
    printf("Hello World!");
}

我如何 link 将它们组合在一起并将它们编译成我可以在 qemu/any 普通计算机上打开的东西?

How to properly create a kernel in C and link to bootloader

不要。

一个 OS 通常是许多独立的可执行文件(引导加载程序、内核、GUI、文本编辑器、Web 浏览器...),它们没有链接在一起成为一个可以完成所有事情的大文件(例如"Ubuntu.exe").

用于 80x86 的引导加载程序;一般来说,你可能有:

  • 用于 BI 的引导加载程序OS 专为未分区的存储设备(例如古老的软盘)设计
  • 用于 BI 的引导加载程序OS 专为 "MBR partitioned" 存储设备设计
  • 用于 BI 的引导加载程序OS 专为 "GPT partitioned" 存储设备设计
  • 用于 BI 的引导加载程序OS 专为可引导 CD ("no emulation El Torito")
  • 用于 BIOS 的引导加载程序,专为 PXE/network 引导而设计
  • 设计了 UEFI 的引导加载程序(并为 32 位编译)
  • 设计了 UEFI 的引导加载程序(并针对 64 位编译)

其中每一件事都涉及一些非常不同的代码(引导加载程序文件格式、固件限制、固件 API、从何处获取内核等)。

您要确保您的任何引导加载程序都可以使用相同的内核(并确保某个可能是错误的特定引导加载程序尚未与内核一起构建 into/linked)。

不要忘记(最终,不是在早期开发期间)最终用户 download/obtain 某种 "OS installer";并且 "OS installer" 确定要使用 OS 安装的正确引导加载程序(可能在询问用户 if/where/how 他们想要安装 OS 并检测到各种信息后关于正在安装 OS 的计算机——什么类型的 CPU、什么类型的固件、什么类型的分区方案,...)。在 "OS installer" 完成大量工作之前,您无法知道哪个引导加载程序是正确的引导加载程序(并且在构建项目时无法知道哪个引导加载程序是正确的引导加载程序)。