三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

OSASK学习第1天:从计算机结构到汇编程序入门

OSASK学习第1天:从计算机结构到汇编程序入门

1. 先动手做起来

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

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

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

写入 16 进制数据

0000-0082 的内容:

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

01E0-0202 的内容:

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 中,不用安装)。

方式二:VMware 启动

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

启动失败时遇到的问题

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

2. 究竟做了什么

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

3. 初次体验汇编程序

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

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

DB0xeb,0x4e,0x90,0x48,0x45,0x4c,0x4c,0x4fDB0x49,0x50,0x4c,0x00,0x02,0x01,0x01,0x00DB0x02,0xe0,0x00,0x40,0x0b,0xf0,0x09,0x00DB0x12,0x00,0x02,0x00,0x00,0x00,0x00,0x00DB0x40,0x0b,0x00,0x00,0x00,0x00,0x29,0xffDB0xff,0xff,0xff,0x48,0x45,0x4c,0x4c,0x4fDB0x2d,0x4f,0x53,0x20,0x20,0x20,0x46,0x41DB0x54,0x31,0x32,0x20,0x20,0x20,0x00,0x00RESB16DB0xb8,0x00,0x00,0x8e,0xd0,0xbc,0x00,0x7cDB0x8e,0xd8,0x8e,0xc0,0xbe,0x74,0x7c,0x8aDB0x04,0x83,0xc6,0x01,0x3c,0x00,0x74,0x09DB0xb4,0x0e,0xbb,0x0f,0x00,0xcd,0x10,0xebDB0xee,0xf4,0xeb,0xfd,0x0a,0x0a,0x68,0x65DB0x6c,0x6c,0x6f,0x2c,0x20,0x77,0x6f,0x72DB0x6c,0x64,0x0a,0x00,0x00,0x00,0x00,0x00RESB368DB0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xaaDB0xf0,0xff,0xff,0x00,0x00,0x00,0x00,0x00RESB4600DB0xf0,0xff,0xff,0x00,0x00,0x00,0x00,0x00RESB1469432
  • 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格式软盘专用的代码 DB0xeb,0x4e,0x90DB"HELLOIPL";启动区的名称可以是任意的字符串(8字节) DW512;每个扇区(sector)的大小(必须为512字节) DB1;簇(cluster)的大小(必须为1个扇区) DW1;FAT的起始位置(一般从第一个扇区开始) DB2;FAT的个数(必须为2) DW224;根目录的大小(一般设成224项) DW2880;该磁盘的大小(必须是2880扇区) DB0xf0;磁盘的种类(必须是0xf0) DW9;FAT的长度(必须是9扇区) DW18;1个磁道(track)有几个扇区(必须是18) DW2;磁头数(必须是2) DD0;不使用分区,必须是0DD2880;重写一次磁盘大小 DB0,0,0x29;意义不明,固定 DD0xffffffff;(可能是)卷标号码 DB"HELLO-OS ";磁盘的名称(11字节) DB"FAT12 ";磁盘格式名称(8字节) RESB18;先空出18字节;程序主体 DB0xb8,0x00,0x00,0x8e,0xd0,0xbc,0x00,0x7cDB0x8e,0xd8,0x8e,0xc0,0xbe,0x74,0x7c,0x8aDB0x04,0x83,0xc6,0x01,0x3c,0x00,0x74,0x09DB0xb4,0x0e,0xbb,0x0f,0x00,0xcd,0x10,0xebDB0xee,0xf4,0xeb,0xfd;信息显示部分 DB0x0a,0x0a;2个换行 DB"hello, world"DB0x0a;换行 DB0RESB0x1fe-$;填写0x00,直到0x001feDB0x55,0xaa;以下是启动区以外部分的输出 DB0xf0,0xff,0xff,0x00,0x00,0x00,0x00,0x00RESB4600DB0xf0,0xff,0xff,0x00,0x00,0x00,0x00,0x00RESB1469432
  • “ ; ”:这是个注释命令,相当于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 表 + 根目录区 + 数据区
只有数据区的扇区才会被打包成簇存放文件。

← 返回列表