《30天自制操作系统》笔记-day1
本文最后更新于 2026年7月3日 凌晨
Day1
《30天自制操作系统》是一本从零开始编写一个简易操作系统的书
Day1,这一章没通过C或其他高级语言来实现,主要是通过十六进制编辑器和汇编语言制作一个IPL(Initial Program Loader,初始程序加载器)
IPL(Initial Program Loader,初始程序加载器):就是BIOS加载的第一个扇区,为后续的学习提供了基础
二进制编写的img文件
img文件主要部分,字节排列为小端序
BPB及EBPB区域
起始偏移位置:0x00
| 偏移 | 字节 | 含义 |
|---|---|---|
| 0x00 | 0xEB 0x4E 0x90 | 跳转指令(跳过 BPB 到引导代码) |
| 0x03 | 0x48 0x45 0x4C 0x4C 0x4F 0x49 0x50 0x4C | 字符串”HELLOIPL”(可任意),启动区名称 |
| 0x0B | 0x00 0x02 | 每个扇区的大小(必须是512byte) |
| 0x0D | 0x01 | 簇的大小(必须是一个扇区) |
| 0x0E | 0x01 0x00 | FAT的起始位置 |
| 0x10 | 0x02 | FAT的个数 |
| 0x11 | 0xE0 0x00 | 根目录的大小(一般为224项) |
| 0x13 | 0x40 0x0B | 磁盘大小(必须是2880扇区) |
| 0x15 | 0xF0 | 磁盘种类(必须是F0) |
| 0x16 | 0x09 0x00 | FAT长度(必须是9扇区) |
| 0x18 | 0x12 0x00 | 1个磁道有多少个扇区(必须是18) |
| 0x1A | 0x02 0x00 | 磁头数(必须是2) |
| 0x1C | 0x00 0x00 0x00 0x00 | 不使用分区,必须是0 |
| 0x20 | 0x40 0x0B 0x00 0x00 | 重写一次磁盘大小 |
| 0x24 | 0x00 | 驱动器号 = 0x00(软盘 A:) |
| 0x25 | 0x00 | 保留字节 |
| 0x26 | 0x29 | 扩展签名 0x29,表示后面三个字段有效 |
| 0x27 | 0xFF 0xFF 0xFF 0xFF | 卷序列号(这里写了全F,可能是随意占位) |
| 0x2B | 0x48 0x45 0x4C 0x4C 0x4F 0x2D 0x4F 0x53 0x20 0x20 0x20 | “HELLO-OS “磁盘名称(11byte) |
| 0x36 | 0x46 0x41 0x54 0x31 0x32 0x20 0x20 0x20 | “FAT12 “磁盘格式名称(8byte) |
十六进制编辑器内容:
1 | |
保留区域 + 引导代码 + 数据
起始偏移位置:0x3E
| 偏移 | 字段 | 含义 |
|---|---|---|
| 0x3E | 0x00 …… 0x00 | 空出了18个字节 |
| 0x50 | 0xB8 0x00 0x00 0x8E 0xD0 0xBC 0x00 0x7C 0x8E 0xD8 0x8E 0xC0 0xBE 0x74 0x7C 0x8A 0x04 0x83 0xC6 0x01 0x3C 0x00 0x74 0x09 0xB4 0x0E 0xBB 0x0F 0x00 0xCD 0x10 0xEB 0xEE 0xF4 0xEB 0xFD | 引导代码本体(36字节,实模式) |
| 0x74 | 0x0A 0x0A 0x68 0x65 0x6C 0x6C 0x6F 0x2C 0x20 0x77 0x6F 0x72 0x6C 0x64 0x0A 0x00 | 输出hello, world 格式:0A 0A “hello, world” 0A 00 |
| 0x83 | 0x00 …… 0x00 | 全0补位到510字节 |
十六进制编辑器内容:
1 | |
启动签名
起始偏移位置:0x1F0
| 偏移 | 字段 | 含义 |
|---|---|---|
| 0x1F0 | 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 | 续上表全0补位 |
| 0x1FE | 0x55 0xAA | 启动扇区签名。BIOS 以此识别可引导设备 |
十六进制编辑器内容:
1 | |
占位标记
纯占位标记,无具体意义
起始偏移位置:0x200和0x1400
1 | |
1 | |
汇编语言
DB指令
define byte直接往字节里面写一个字节
1 | |
可以直接写字符串,转成机器语言的时候会自动查询转换
1 | |
DW指令与DD指令
都与DB类似define word两个字节define double-word四个字节
RESB指令
reserve byte空出指定字节数的空间
1 | |
$ 符号
$是NASM汇编器的一个特殊符号,表示当前指令的地址(即前面所有代码的字节数之和)。
它在计算偏移量和填充空间时非常实用。
例如:
1 | |
这段代码的含义是:用RESB把剩余空间填 0, 直到地址恰好到达 0x1FE(510),然后写入0x55 0xAA 启动签名。 这就保证签名始终位于扇区的最后两个字节。
下图中鼠标选中的字节就是当前$的数值:
程序
1 | |
以上汇编代码分为三部分:
- FAT12 头部:定义磁盘参数,BIOS 据此识别磁盘格式
- 程序主体 + 信息显示:x86 实模式代码,调用
INT 0x10打印hello, world - 扇区外填充:把镜像撑到 1.44MB,中间用
F0 FF FF做标记
汇编语言转机器语言
1 | |
生成helloos.img镜像文件
启动:
小结
Day1的核心收获
- 一个可引导的磁盘镜像需要在前
512字节中包含FAT头部+引导代码+0x55AA签名 DB/DW/DD直接定义1/2/4字节RESB用于填充空间$代表当前地址,配合RESB可以来控制数据位置
《30天自制操作系统》笔记-day1
https://www.ming-ice-tea.top/2026/07/02/《30天自制操作系统》笔记-day1/