1. 先动手做起来

首先,按照书中的要求下载一个二进制编辑器:BZ,下载地址如下:

http://www.vcraft.jp/soft/bz.html

然后输入下图所示的 16 进制数据,并保存为名为 helloos.img 的软盘映像文件。

写入 16 进制数据

0000-0082 的内容:

0000-0082

Note: 原文这里缺少一部分内容,不过紧接着后面的章节就有介绍。

01E0-0202 的内容:

01E0-0202

1400-1402 的内容:

1400-1402

剩下的地址直到 168000 全部为 0,正好是 1474560 = 1440 × 1024 字节。

创建工程目录与批处理文件

在之前(第 0 节)下载的工具中有一个 tolset 文件夹,在里面新建 helloos0 作为工作目录,然后把 z_new_w\!cons_nt.bat 复制到当前目录,并新建 run.batinstall.bat 两个批处理文件。右键编辑两个文件的内容:

run.bat

copy helloos.img ..\z_tools\qemu\fdimage0.bin
..\z_tools\make.exe -C ../z_tools/qemu

install.bat

..\z_tools\imgtol.com w a: helloos.img

接下来只需要启动这个操作系统就可以了。

启动方式

方式一:QEMU 启动

双击 !cons_nt.bat,在打开的命令行中输入 run,会启动 QEMU 窗口进行显示(QEMU 已经包含在 tolset 中,不用安装)。

QEMU 启动效果

方式二:VMware 启动

可以参考这个博客链接:VMware 虚拟机启动 img 文件

VMware 启动效果

启动失败时遇到的问题

我第一次用 QEMU 的方式启动时没有启动成功,后来检查发现是因为在编辑 run.bat 文件时,把 ../z_tools/qemu 中的斜杠方向写反了,写成了 ..\z_tools\qemu,导致启动失败。

2. 究竟做了什么

这部分主要介绍的是CPU只能处理电信号,用电信号表示0和1,以及二进制和十六进制等比较基础的问题

3. 初次体验汇编程序

本节使用作者川合秀实基于自由软件汇编器 “NASM” 自制的汇编语言编译器 “NASK” ,把一个汇编程序编译为二进制img文件。

首先新建一个hellooos1文件夹,并在里面创建一个名 helloos.nas 的文件

DB  0xeb, 0x4e, 0x90, 0x48, 0x45, 0x4c, 0x4c, 0x4f
DB  0x49, 0x50, 0x4c, 0x00, 0x02, 0x01, 0x01, 0x00
DB  0x02, 0xe0, 0x00, 0x40, 0x0b, 0xf0, 0x09, 0x00
DB  0x12, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
DB  0x40, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x29, 0xff
DB  0xff, 0xff, 0xff, 0x48, 0x45, 0x4c, 0x4c, 0x4f
DB  0x2d, 0x4f, 0x53, 0x20, 0x20, 0x20, 0x46, 0x41
DB  0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00
RESB     16
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, 0x0a, 0x0a, 0x68, 0x65
DB  0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72
DB  0x6c, 0x64, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00
RESB     368
DB  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
DB  0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
RESB     4600
DB  0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
RESB     1469432
  • DB 指令是“define byte”的缩写,也就是往文件里直接写入1个字节的指令。
  • RESB 指令是“reserve byte”的略写,如果想要从现在的地址开始空出10个字节来,就可以写成RESB 10,意思是我们预约了这10个字节。
  • 数字的前面加上0x,就成了十六进制数,不加0x,就是十进制数。这一点跟C语言是一样的。

然后做一个批处理文件asm.bat,里面命令如下:

..\z_tools\nask.exe hello.nas hello.img

可以看到这个指令调用nask把nas汇编文件,编译为了img文件
在这里插入图片描述

4. 加工润色

这一节就是对 nas 汇编文件做了一些注释,并介绍了几种操作系统的专业术语

; hello-os
; TAB=4

; 以下这段是标准FAT12格式软盘专用的代码

        DB    0xeb, 0x4e, 0x90
        DB    "HELLOIPL"      ; 启动区的名称可以是任意的字符串(8字节)
        DW    512              ; 每个扇区(sector)的大小(必须为512字节)
        DB    1                ; 簇(cluster)的大小(必须为1个扇区)
        DW    1          ; FAT的起始位置(一般从第一个扇区开始)
        DB    2          ; FAT的个数(必须为2)
        DW    224       ; 根目录的大小(一般设成224项)
        DW    2880      ; 该磁盘的大小(必须是2880扇区)
        DB    0xf0      ; 磁盘的种类(必须是0xf0)
        DW    9          ; FAT的长度(必须是9扇区)
        DW    18         ; 1个磁道(track)有几个扇区(必须是18)
        DW    2          ; 磁头数(必须是2)
        DD    0          ; 不使用分区,必须是0
        DD    2880      ; 重写一次磁盘大小
        DB    0,0,0x29        ; 意义不明,固定
        DD    0xffffffff      ;(可能是)卷标号码
        DB    "HELLO-OS   "   ; 磁盘的名称(11字节)
        DB    "FAT12   "      ; 磁盘格式名称(8字节)
        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      ; 2个换行
        DB    "hello, world"
        DB    0x0a             ; 换行
        DB    0

        RESB  0x1fe-$         ; 填写0x00,直到 0x001fe
        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
  • “ ; ”:这是个注释命令,相当于C语言或是C++中的“//”​。
  • DB指令的新用法,可以直接用它写字符串。
  • “ $ ”:这个美元符号是一个变量,可以告诉我们这一行现在的字节数。通过 0x1fe-$ 这句汇编语言,可以自动计算需要输出多少个00。

专业术语:

  • TAB=4
  • FAT12格式: 软盘经典文件系统,这个格式兼容性好,在Windows上也能用。
  • 启动区: 软盘第一个的扇区称为启动区。因为计算机首先从最初一个扇区开始读软盘,然后去检查这个扇区最后2个字节的内容。如果这最后2个字节不是0x55 AA,计算机会认为这张盘上没有所需的启动程序,就会报一个不能启动的错误
  • IPL(initial program loader)启动程序加载器:
  • 启动

扇区、簇、软盘容量三者简明关系

1. 扇区(磁盘最小物理读写单位)

软盘硬件层面最小读写单元:1 扇区 = 512 字节
BIOS、磁盘硬件只能按整扇区读写,不能只读写半个扇区。

2. 簇(文件系统最小分配单位,逻辑单位)

操作系统不会直接按扇区给文件分配空间,而是把连续多个扇区打包成 1 簇。
1 簇 = N 个连续扇区

经典 1.44MB 软盘 FAT12:1 簇 = 1 个扇区(512 字节)

文件占用空间永远按整簇分配;哪怕文件只有 1 字节,也要占一整个簇。

3. 三者计算公式

总容量
总字节数 = 总扇区数 × 每扇区字节数 (512B)
簇总数
总簇数 = 数据区总扇区数 ÷ 每簇扇区数

FAT12 名字由来 用12 位二进制记录每一个簇的状态(空闲、被占用、文件末尾、下一簇编号),所以叫 FAT12。

4. 以 1.44MB 标准软盘举例演算

硬件参数: 80 磁道、2 个磁头、每道 18 扇区
总扇区 = 80×2×18 = 2880 扇区
总容量 = 2880 × 512 = 1474560 B = 1440KB ≈ 1.44MB
空间拆分:
总扇区 2880 = 引导扇区 + 两份 FAT 表 + 根目录区 + 数据区
只有数据区的扇区才会被打包成簇存放文件。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐