理论讲解:BIOS与启动过程
1. 按下电源后发生了什么
当你按下电源键,计算机经历以下步骤:
① CPU上电,跳转到固定地址 0xFFFFFFF0
↓
② 执行BIOS/UEFI代码
↓
③ POST(加电自检)
- 检查CPU、内存、显卡等硬件
↓
④ 初始化硬件设备
- 设置中断向量表
- 初始化显卡(文本模式)
↓
⑤ 查找引导设备
- 按设定顺序检查:软盘、硬盘、光盘、USB...
↓
⑥ 加载引导扇区
- 读取第一个扇区(512字节)到内存地址 0x7C00
- 检查最后两字节是否为 0x55AA
↓
⑦ 跳转到 0x7C00 执行
- 控制权从BIOS转移到我们的代码!
📝 这时CPU处于实模式(16位),可访问的内存只有1MB。
2. BIOS的职责
BIOS(Basic Input/Output System)的核心职责:
- 硬件自检和初始化 — 确保硬件正常
- 提供基本I/O服务 — 通过中断调用(int指令)
- 加载引导程序 — 从磁盘读取第一个扇区
BIOS中断服务
BIOS通过中断提供基本服务,我们在引导阶段会频繁使用:
| 中断号 | 用途 | 常用功能 |
|---|---|---|
| INT 0x10 | 视频服务 | 打印字符、设置光标、清屏 |
| INT 0x13 | 磁盘服务 | 读写磁盘扇区 |
| INT 0x15 | 系统服务 | 获取内存大小 |
| INT 0x16 | 键盘服务 | 读取键盘输入 |
示例 — 打印字符:
mov ah, 0x0E ; 功能号:teletype输出
mov al, 'H' ; 要打印的字符
int 0x10 ; 调用视频中断⚠️ BIOS中断只能在实模式下使用。进入保护模式后就不能用了。
3. 主引导记录(MBR)
结构
MBR位于磁盘的第一个扇区(LBA 0),共512字节:
偏移 大小 内容
───────────────────────────────
0x000 446字节 引导代码(我们写的代码)
0x1BE 16字节 分区表项1
0x1CE 16字节 分区表项2
0x1DE 16字节 分区表项3
0x1EE 16字节 分区表项4
0x1FE 2字节 引导签名 0x55 0xAA
关键约束
- 总大小为512字节 — 引导代码最多用446字节
- 必须以 0xAA55 结尾 — BIOS通过这个签名判断是否是有效的引导扇区
- 加载地址为 0x7C00 — 所有地址计算基于此
为什么是 0x7C00?
这是IBM PC设计时定下的地址。0x7C00 = 32KB - 1024B,选择这个位置是为了:
- 在低端内存中留出足够空间给中断向量表和BIOS数据
- 在引导扇区代码下方留出空间给栈使用
- 0x7C00之上还有大量可用内存
4. 编写最简单的引导扇区
现在你已经了解了启动过程,让我们动手编写第一个引导扇区代码。
进入 code 目录查看完整代码和运行说明。
核心代码预览:
[BITS 16] ; 告诉汇编器生成16位代码
[ORG 0x7C00] ; 告诉汇编器代码从0x7C00开始
start:
mov ah, 0x0E ; BIOS功能:打印字符
mov al, 'A' ; 要打印的字符
int 0x10 ; 调用BIOS视频中断
jmp $ ; 无限循环($ = 当前地址)
times 510-($-$$) db 0 ; 用0填充到510字节
dw 0xAA55 ; 引导签名(小端序:先55后AA)理解每一行:
| 代码 | 含义 |
|---|---|
[BITS 16] | CPU现在是16位实模式 |
[ORG 0x7C00] | BIOS把我们加载到了这个地址 |
mov ah, 0x0E | 选择BIOS的”打印字符”功能 |
mov al, 'A' | 把字符’A’放入AL寄存器 |
int 0x10 | 触发BIOS视频中断 |
jmp $ | 死循环(没有更多代码要执行) |
times 510-($-$$) db 0 | 填充剩余空间为0 |
dw 0xAA55 | 引导签名,让BIOS认可这是引导扇区 |
5. 与OS其他部分的关系
引导扇区是操作系统的起点。后续章节将在此基础上:
第3章 引导扇区(当前)
└→ 第4章 Bootloader(从磁盘加载更多代码)
└→ 第5章 保护模式(从16位切换到32位)
└→ 第6章 加载C内核
参考资料
- OSDev Wiki - Boot Sequence
- OSDev Wiki - MBR
- Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 3, Chapter 9