《30天自制操作系统》 Day1学习笔记

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)

十六进制编辑器内容:

r 复制代码
EB 4E 90 48 45 4C 4C 4F 49 50 4C 00 02 01 01 00 02 E0 00 40 0B F0 09 00 12 00 02 00 00 00 00 00 40 0B 00 00 00 00 29 FF FF FF FF 48 45 4C 4C 4F 2D 4F 53 20 20 20 46 41 54 31 32 20 20 20

保留区域 + 引导代码 + 数据

起始偏移位置: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字节

十六进制编辑器内容:

r 复制代码
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B8 00 00 8E D0 BC 00 7C 8E D8 8E C0 BE 74 7C 8A 04 83 C6 01 3C 00 74 09 B4 0E BB 0F 00 CD 10 EB EE F4 EB FD 0A 0A 68 65 6C 6C 6F 2C 20 77 6F 72 6C 64 0A 00 00 00 00 00 00 00 00 00 00 00 00 00

启动签名

起始偏移位置:0x1F0

偏移 字段 含义
0x1F0 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 续上表全0补位
0x1FE 0x55 0xAA 启动扇区签名。BIOS 以此识别可引导设备

十六进制编辑器内容:

复制代码
00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA 

占位标记

纯占位标记,无具体意义 起始偏移位置:0x2000x1400

复制代码
F0 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00

F0 FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00

汇编语言

DB指令

define byte直接往字节里面写一个字节

markdown 复制代码
    DB 0xEB, 0x4E, 0x90, 0x48, 0x45, 0x4C, 0x4C, 0x4F

可以直接写字符串,转成机器语言的时候会自动查询转换

arduino 复制代码
	DB  "hello, world"

DW指令与DD指令

都与DB类似 define word两个字节 define double-word四个字节

RESB指令

reserve byte空出指定字节数的空间

ini 复制代码
    RESB    16 ;空出了十六个字节

$ 符号

$是NASM汇编器的一个特殊符号,表示当前指令的地址(即前面所有代码的字节数之和)。 它在计算偏移量和填充空间时非常实用。

例如:

asm 复制代码
RESB 0x1FE - $   ; 用 0 填充到第 510 字节
DB   0x55, 0xAA  ; 在第 511、512 字节写入启动签名

这段代码的含义是:用RESB把剩余空间填 0, 直到地址恰好到达 0x1FE(510),然后写入0x55 0xAA 启动签名。 这就保证签名始终位于扇区的最后两个字节。

下图中鼠标选中的字节就是当前$的数值:

程序

ini 复制代码
; hello-os
; TAB=4

; FAT12格式软盘的专用代码

    DB 0xEB, 0x4E, 0x90
    DB "HELLOIPL"   ; 启动区名称(任意字符串)
    DW 512          ; 每个扇区大小(必须是512byte)
    DB 1            ; 簇的大小(必须是一个扇区)
    DW 1            ; FAT的起始位置
    DB 2            ; FAT的个数
    DW 224          ; 根目录的大小(一般为224项)
    DW 2880         ; 磁盘大小(必须是2880扇区)
    DB 0xF0         ; 磁盘种类(必须是F0)
    DW 9            ; FAT长度(必须是9扇区)
    DW 18           ; 1个磁道有多少个扇区(必须是18)
    DW 2            ; 磁头数(必须是2)
    DD 0            ; 不使用分区,必须是0
    DD 2880         ; 重写一次磁盘大小
    DB 0,0,0x29     ; 意义不明,固定
    DD 0xFFFFFFFF   ; (可能是)卷标号码
    DB "HELLO-OS   "; 磁盘名称(11byte)
    DB "FAT12   "   ; 磁盘格式名称(8byte)
    RESB 18         ; 空出18个字节

; 程序主体
    DB  0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c     
    DB  0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a     
    DB  0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09     
    DB  0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb     
    DB  0xee, 0xf4, 0xeb, 0xfd
    
; 信息显示部分
    DB  0x0a, 0x0a
    DB  "hello, world"
    DB  0x0a
    DB  0x00
    
    RESB 0x1FE-$ ; $是一个变量,指前面的字节数,这个计算转成十进制就是510-132
    DB  0x55, 0xaa

; 启动区以外部分的输出
    DB  0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00     
    RESB    4600 
    DB  0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00     
    RESB    1469432

以上汇编代码分为三部分:

  1. FAT12 头部:定义磁盘参数,BIOS 据此识别磁盘格式
  2. 程序主体 + 信息显示 :x86 实模式代码,调用 INT 0x10 打印 hello, world
  3. 扇区外填充 :把镜像撑到 1.44MB,中间用 F0 FF FF 做标记

汇编语言转机器语言

shell 复制代码
..\z_tools\nask.exe helloos.nas helloos.img

生成helloos.img镜像文件

启动:

小结

Day1的核心收获

  1. 一个可引导的磁盘镜像需要在前512字节中包含FAT头部+引导代码+0x55AA签名
  2. DB/DW/DD直接定义1/2/4字节
  3. RESB用于填充空间
  4. $代表当前地址,配合RESB可以来控制数据位置

本文首发于我的个人博客文章链接

相关推荐
小宇子2B6 小时前
vm_area_struct:进程地址空间的合法区间表
操作系统
星马梦缘1 天前
操作系统计算题专项练习(15题)
操作系统·os·银行家算法·段页式
小宇子2B2 天前
物理内存的地图:node、zone、page frame 和 struct page
操作系统
阿昭L2 天前
操作系统复习(九)
操作系统
阿昭L2 天前
操作系统复习(七)
操作系统
小宇子2B3 天前
虚拟地址不是内存:Linux 如何切开一个进程的地址空间
操作系统
饼干哥哥5 天前
ChatGPT会员掉了,代充黑幕藏不住了
人工智能·操作系统·产品
小宇子2B5 天前
五、内核里的 GS / swapgs,与现代 TSS
操作系统
小宇子2B6 天前
四、x86-64 的简化:段机制基本退场,FS/GS 为什么留下
操作系统