背景

构建一个极简的 x86 引导程序,运行于 16 位实模式,执行以下基本操作:

  1. 引导加载初始化
  2. 设置视频模式
  3. 显示启动信息
  4. 系统停止运行

启动过程

引导程序的执行流程如下:

  1. BIOS 将引导扇区加载至内存地址 0x7C00
  2. 初始化段寄存器和堆栈
  3. 设置文本模式,并在屏幕上打印 "Booted!"
  4. 系统停止,进入死循环

项目目标

提供一个精简、直观的引导加载器示例,用于演示以下内容:

  • BIOS 基本交互(视频服务调用)
  • 引导扇区的结构与构建规范
  • 实模式下输出字符串到屏幕

该引导程序不包含高级功能(如磁盘读写、命令解析等),但可作为理解引导机制的起点

引导扇区规范说明:

  • 文件大小需为 512 字节
  • 使用 times 510-($-$$) db 0 填充空白区域
  • 0xAA55 签名结尾,供 BIOS 识别为有效引导扇区

示例代码:boot.asm

用 NASM 编写的引导扇区汇编代码

[org 0x7C00]          ; BIOS 加载引导扇区的默认地址
bits 16               ; 指定 16 位代码(实模式)

start:
    ; 初始化段寄存器
    cli               ; 清除中断
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7C00    ; 设置堆栈顶
    sti               ; 启用中断

    ; 设置视频模式为 80x25 文本模式 (BIOS 中断 10h, 功能 00h)
    mov ah, 0x00
    mov al, 0x03
    int 0x10

    ; 显示字符串 "Booted!",使用 BIOS 中断 10h 的逐字符输出
    mov si, message

.print_char:
    lodsb              ; 加载下一个字符到 AL,并自动 SI++
    cmp al, 0
    je .halt           ; 如果是 null 字符,结束
    mov ah, 0x0E       ; BIOS teletype 输出功能
    mov bh, 0x00       ; 页面号
    mov bl, 0x07       ; 属性(灰色前景,黑色背景)
    int 0x10
    jmp .print_char

.halt:
    cli
    hlt                ; 停止系统,等待中断
    jmp .halt          ; 死循环防止继续执行

message db 'Booted!', 0

; 填充引导扇区到 512 字节
times 510 - ($ - $$) db 0
dw 0xAA55              ; 引导扇区签名(必须)

编译与运行说明

编译(使用 NASM)

nasm -f bin boot.asm -o boot.bin

在 QEMU 中测试

qemu-system-i386 -drive file=boot.bin,format=raw

说明与分析

  • [org 0x7C00]

    指示汇编器假定该程序加载在 0x7C00 地址,这是 BIOS 加载引导扇区的标准位置

  • 段寄存器初始化

    实模式下,段寄存器必须显式初始化,常设为 0x0000 以便段地址从 0 开始

  • 文本模式设置

    BIOS 中断 INT 0x10 提供多种视频服务。功能号 AH=0x00AL=0x03 切换到 80x25 文本模式

  • 字符串显示

    使用 BIOS INT 0x10AH=0x0E 功能一字符一字符地输出 ASCII

  • 引导扇区要求

    • 大小必须精确为 512 字节
    • 最后两个字节为 0xAA55(小端存储为 55 AA
    • 否则 BIOS 将忽略该扇区,跳过启动

ref

https://www.linkedin.com/pulse/minimal-os-qemu-hani-fahmi-augge/