Day2 汇编语言学习与Makefile入门

本文仅带着思路,研究源码里关于文件系统的参数

关于day2主程序部分及更多内容,请看《30天自制操作系统》笔记

导航

  1. 发现学习中的变化
  2. 源码差异分析
  3. FAT12/FAT16/FAT32相关资料
  4. 开始全面分析

发现学习中的变化

day1代码(只简单地使用DB DW DD RESB指令)

 1 ; hello-os
2 ; TAB=4
3
4 ; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy code
5
6 DB 0xeb, 0x4e, 0x90
7 DB "HELLOIPL" ; 启动扇区名称(8字节)
8 DW 512 ; 每个扇区(sector)大小(必须512字节)
9 DB 1 ; 簇(cluster)大小(必须为1个扇区)
10 DW 1 ; FAT起始位置(一般为第一个扇区)
11 DB 2 ; FAT个数(必须为2)
12 DW 224 ; 根目录大小(一般为224项)
13 DW 2880 ; 该磁盘大小(必须为2880扇区1440*1024/512)
14 DB 0xf0 ; 磁盘类型(必须为0xf0)
15 DW 9 ; FAT的长度(必??9扇区)
16 DW 18 ; 一个磁道(track)有几个扇区(必须为18)
17 DW 2 ; 磁头数(必??2)
18 DD 0 ; 不使用分区,必须是0
19 DD 2880 ; 重写一次磁盘大小
20 DB 0,0,0x29 ; 意义不明(固定)
21 DD 0xffffffff ; (可能是)卷标号码
22 DB "HELLO-OS " ; 磁盘的名称(必须为11字?,不足填空格)
23 DB "FAT12 " ; 磁盘格式名称(必??8字?,不足填空格)
24 RESB 18 ; 先空出18字节
25
26 ; 程序主体
27
28 DB 0xb8, 0x00, 0x00, 0x8e, 0xd0, 0xbc, 0x00, 0x7c
29 DB 0x8e, 0xd8, 0x8e, 0xc0, 0xbe, 0x74, 0x7c, 0x8a
30 DB 0x04, 0x83, 0xc6, 0x01, 0x3c, 0x00, 0x74, 0x09
31 DB 0xb4, 0x0e, 0xbb, 0x0f, 0x00, 0xcd, 0x10, 0xeb
32 DB 0xee, 0xf4, 0xeb, 0xfd
33
34 ; 信息显示部分
35
36 DB 0x0a, 0x0a ; 换行两次
37 DB "hello, world"
38 DB 0x0a ; 换行
39 DB 0
40
41 RESB 0x1fe-$ ; 填写0x00直到0x001fe
42
43 DB 0x55, 0xaa
44
45 ; 启动扇区以外部分输出
46
47 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
48 RESB 4600
49 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
50 RESB 1469432

以下是day2代码(使用了真正的汇编指令,编译出来的文件和day1的完全一致,我用二进制文件对比工具对比过了)

 1 ; hello-os
2 ; TAB=4
3
4 ORG 0x7c00 ; 指明程序装载地址
5
6 ; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy code
7
8 JMP entry
9 DB 0x90
10 DB "HELLOIPL" ; 启动扇区名称(8字节)
11 DW 512 ; 每个扇区(sector)大小(必须512字节)
12 DB 1 ; 簇(cluster)大小(必须为1个扇区)
13 DW 1 ; FAT起始位置(一般为第一个扇区)
14 DB 2 ; FAT个数(必须为2)
15 DW 224 ; 根目录大小(一般为224项)
16 DW 2880 ; 该磁盘大小(必须为2880扇区1440*1024/512)
17 DB 0xf0 ; 磁盘类型(必须为0xf0)
18 DW 9 ; FAT的长度(必??9扇区)
19 DW 18 ; 一个磁道(track)有几个扇区(必须为18)
20 DW 2 ; 磁头数(必??2)
21 DD 0 ; 不使用分区,必须是0
22 DD 2880 ; 重写一次磁盘大小
23 DB 0,0,0x29 ; 意义不明(固定)
24 DD 0xffffffff ; (可能是)卷标号码
25 DB "HELLO-OS " ; 磁盘的名称(必须为11字?,不足填空格)
26 DB "FAT12 " ; 磁盘格式名称(必??8字?,不足填空格)
27 RESB 18 ; 先空出18字节
28
29 ; 程序主体
30
31 entry:
32 MOV AX,0 ; 初始化寄存器
33 MOV SS,AX
34 MOV SP,0x7c00
35 MOV DS,AX
36 MOV ES,AX
37
38 MOV SI,msg
39 putloop:
40 MOV AL,[SI]
41 ADD SI,1 ; 给SI加1
42 CMP AL,0
43 JE fin
44 MOV AH,0x0e ; 显示一个文字
45 MOV BX,15 ; 指定字符颜色
46 INT 0x10 ; 调用显卡BIOS
47 JMP putloop
48 fin:
49 HLT ; 让CPU停止,等待指令
50 JMP fin ; 无限循环
51
52 msg:
53 DB 0x0a, 0x0a ; 换行两次
54 DB "hello, world"
55 DB 0x0a ; 换行
56 DB 0
57
58 RESB 0x7dfe-$ ; 填写0x00直到0x001fe
59
60 DB 0x55, 0xaa
61
62 ; 启动扇区以外部分输出
63
64 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
65 RESB 4600
66 DB 0xf0, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00
67 RESB 1469432

注意:RESB    0x7dfe-$        ; 填写0x00直到0x001fe这一行没有错,编译出来的二进制的确能和day一致

所以我们要研究出:day2与day1汇编代码对应关系,如MOV AX,0是怎么表达成二进制的

首先是这个ORG 0x7c00,对比后面的

0x7dfe-$竟然和0x1fe-$一样,而且7dfe与1fe刚好差了7c00,结合注释,推断这个ORG规定了在内存中被开始加载的地址

ORG 0x7c00  就是让主板从内存0x7c00处开始加载我们写的helloos.img。

可以猜得出,day1版本是用了相对地址,在源码中 把helloos.img的开头用0x0000表示,所以实际在哪个内存地址被加载 应该是由汇编编译器或主板BIOS决定的,

而day2用了绝对地址,指定helloos.img要在内存0x7c00处加载。

先找不同

↑↑↑上半部分源码,      下半部分源码↓↓↓

FAT资料

这个0xeb 0x4e 0x90是什么意思我们还不知道,他就用汇编改了,所以有重点,搜索一下发现了一篇:

[第1天] 二进制代码和nasm

file allocation table - 16bit: http://www.beginningtoseethelight.org/fat16/index.htm 以及

FAT32中文版分析+补充(1)和 FAT32中文版分析+补充(2)

这里引用这篇文章里的 BS_jmpBoot    (跳转指令),如图

所以helloos可能不能在非Intel x86架构的主板上工作?

好了,看完资料,我们发现书中的启动区源码是为FAT12格式软盘服务的,所以如果以后我们要做fat32(甚至需要主板驱动支持的exfat、NTFS),就需要自己去找对应分区格式的启动区参数。


开始全面分析

从day1的启动区开始吧,再贴一次图片,方便对比

Day1的helloOS.nas前半部分

后半部分(程序主体、信息显示部分、启动扇区以外部分输出)

 

 开头的 eb 4e 90,结合fat启动区分区分析图,可以知道在Intel x86里这就是JMP 0x4e,而3e到4f是都是零,4e刚好位于程序主体前面的两个0x00。那这里4e能不能写成3e到50里任意hex呢?用改img文件的十六进制就可以测试。

day2里面把程序主体写作entry,所以源码里的JMP entry就和0xeb 0x4e 0x90作用相同了:

Ps.作者在书里解释说是JMP 0x7c50

而JMP entry下面的东西是fat12的分区扇区参数。(分区扇区参数的都是计算机行业规定,一般不能自己随便改的),如图(引用自FAT32中文版分析+补充(1))

刚好就对应着我们的

0x00到0x10(0x0F是15,0x10就是16,偏移量16就是0x10)

偏移量 启动分区[boot sector] helloos里的值 大小 helloos值的说明
0x0 BS_jmpBoot(跳转指令) 4E 3bits 跳转到指定地址4E
0x3 BS_OEMName(OEM、OS版本号) HELLOIPL 8bits 操作系统名字

零扇区BPB[BIOS Parameter Block]从下面内容可以看出它的作用,即储存了文件系统的参数信息

偏移量 零扇区BPB helloos里的值 大小 helloos值的说明
0xB BPB_BytesPersec(每扇字节数) 512 2bits

可填512,1024,2048,4096,

由于书里用的软盘,所以是512

0xC BPB_SecPerClus(每簇扇区数) 1 1bit 2^n, (n>=0)
0xD BPB_RsvdSecCnt(保留扇区数) 1 2bits FAT12/16硬性规定为1,FAT32为32
0x10 BPB_NumFATs(FAT副本数) 2 1bit FAT 建议写2

从0x11到20

偏移量   helloos里的值 大小 helloos值的说明
0x11  BPB_RootEntCnt(根目录项数)  224  2bits  FAT12/16为32的偶数倍,FAT32必须为0
 0x13  BPB_TotSec16(总扇区数)  2880  2bits  FAT12/16填总扇区数
 0x15  BPB_Media(媒体描述符)  0xf0  1bit  可移动存储介质经常使用0xF0
 0x16  BPB_FATSz16(每FAT扇区数)  9  2bits  FAT12/16一个FAT表所占的扇区数
 0x18  BPB_SecPerTrk(每磁道扇区数)  18  2bits  每磁道扇区数,这个数用于BIOS中断0x13
 0x1A  BPB_NumHeads(磁头数)  2  2bits  磁头数,也用于0x13中断
 0x1C  BPB_HiddSec(隐藏扇区数)  0  4bits

FAT分区之前所隐藏的扇区数,

调用0x13中断可得到,

对于没有分区的储存介质,此域必须为0,

具体使用什么由操作系统决定

 0x20  BPB_TotSec32(总扇区数)  2880  4bits

FAT12/16中,若是总扇区>=10000(64KB)

,那么此域就是总扇区

注解:这里的磁头数等东西指的是逻辑上的,如果没有实体,那么指的就是逻辑磁头数。其他参数同理

对比一下源码,这下子就明明白白了

 1 ; hello-os
2 ; TAB=4
3
4 ORG 0x7c00 ; 指明程序装载地址
5
6 ; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy code
7
8 JMP entry
9 DB 0x90
10 DB "HELLOIPL" ; 启动扇区名称(8字节)
11 DW 512 ; 每个扇区(sector)大小(必须512字节)
12 DB 1 ; 簇(cluster)大小(必须为1个扇区)
13 DW 1 ; FAT起始位置(一般为第一个扇区)
14 DB 2 ; FAT个数(必须为2)
15 DW 224 ; 根目录大小(一般为224项)
16 DW 2880 ; 该磁盘大小(必须为2880扇区1440*1024/512)
17 DB 0xf0 ; 磁盘类型(必须为0xf0)
18 DW 9 ; FAT的长度(必??9扇区)
19 DW 18 ; 一个磁道(track)有几个扇区(必须为18)
20 DW 2 ; 磁头数(必??2)
21 DD 0 ; 不使用分区,必须是0
22 DD 2880 ; 重写一次磁盘大小
23
24 ; 以上部分就是表格里描述的
25 ; 下面这部分还没介绍,不急
26 DB 0,0,0x29 ; 意义不明(固定)
27 DD 0xffffffff ; (可能是)卷标号码
28 DB "HELLO-OS " ; 磁盘的名称(必须为11字?,不足填空格)
29 DB "FAT12 " ; 磁盘格式名称(必??8字?,不足填空格)
30 RESB 18 ; 先空出18字节
31
32 ; 程序主体

剩余部分的详细说明在FAT32中文版分析+补充(2),当然也可以看下图的简单说明

此图资料来自:【文件系统】FAT12文件系统简介

Ps.其实还可以用c语言来做一个文件系统写入工具 (用结构体储存分区信息)

最后搜了很久,发现百度百科也有一点记录:https://baike.baidu.com/item/FAt12#ref_[1]_273750 ,维基百科应该有更详细,可惜英文版也被墙了....

通过搜集资料,我们现在不再仅仅只能做FAT12,还能做FAT32的启动甚至是exfat ext ntfs的

到这里,我们明白了整体

第一部分就是启动区描述和文件系统(书中例子为fat12)

第二部分才是系统和程序(HelloWorld)

好,让我们把精力放在第二部分吧:《30天自制操作系统》笔记4 --- (Day2 下节)了解如何写汇编HelloWorld程序

待续更新...


最后附上维基百科资料

以下是维基侧边栏

Open by Kiwix.

《30天自制操作系统》笔记3 --- (Day2 上节)完全解析文件系统的更多相关文章

  1. 《30天自制操作系统》笔记(06)——CPU的32位模式

    <30天自制操作系统>笔记(06)——CPU的32位模式 进度回顾 上一篇中实现了启用鼠标.键盘的功能.屏幕上会显示出用户按键.点击鼠标的情况.这是通过设置硬件的中断函数实现的,可以说硬件 ...

  2. 《30天自制操作系统》笔记(03)——使用Vmware

    <30天自制操作系统>笔记(03)——使用Vmware 进度回顾 在上一篇,实现了用IPL加载OS程序到内存,然后JMP到OS程序这一功能:并且总结出下一步的OS开发结构.但是遇到了真机测 ...

  3. 《30天自制操作系统》笔记(02)——导入C语言

    <30天自制操作系统>笔记(02)——导入C语言 进度回顾 在上一篇,记录了计算机开机时加载IPL程序(initial program loader,一个nas汇编程序)的情况,包括IPL ...

  4. 《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!

    <30天自制操作系统>笔记(01)——hello bitzhuwei's OS! 最初的OS代码 ; hello-os ; TAB=4 ORG 0x7c00 ; 指明程序的装载地址 ; 以 ...

  5. 30天自制操作系统第九天学习笔记(u盘软盘双启动版本)

    暑假学习小日本的那本书:30天自制操作系统 qq交流群:122358078    ,更多学习中的问题.资料,群里分享 environment:开发环境:ubuntu 第九天的课程已学完,确实有点不想写 ...

  6. 《30天自制操作系统》笔记(01)——hello bitzhuwei’s OS!【转】

    转自:http://www.cnblogs.com/bitzhuwei/p/OS-in-30-days-01-hello-bitzhuwei-OS.html 阅读目录(Content) 最初的OS代码 ...

  7. 30天自制操作系统-day2

    30天自制操作系统(linux)-day2 使用简单的汇编语言 首先Centos环境安装nasm,使用vim工具编辑一个os.asm文件,文件内容如下: DB 0xeb, 0x4e, 0x90, 0x ...

  8. 从你的u盘启动:30天自制操作系统第四天u盘启动学习笔记

    暑假学习小日本的那本书:30天自制操作系统 qq交流群:122358078    ,更多学习中的问题.资料,群里分享 developing environment:ubuntu 关于u盘启动自己做的操 ...

  9. 30天自制操作系统第八天学习笔记(u盘软盘双启动版本)

    暑假学习小日本的那本书:30天自制操作系统 qq交流群:122358078    ,更多学习中的问题.资料,群里分享 environment:开发环境:ubuntu 第八天的学习思考: 关于鼠标是怎么 ...

随机推荐

  1. 云原生生态周报 Vol. 15 | K8s 安全审计报告发布

    业界要闻 CNCF 公布 Kubernetes 的安全审计报告 报告收集了社区对 Kubernetes.CoreDNS.Envoy.Prometheus 等项目的安全问题反馈,包含从一般弱点到关键漏洞 ...

  2. Spring Cloud 新一代Web框架微服务翘楚(一)

    序言 springcloud是微服务架构的集大成者,将一系列优秀的组件进行了整合.基于springboot构建,对我们熟悉spring的程序员来说,上手比较容易. 通过一些简单的注解,我们就可以快速的 ...

  3. .net core 3.0中的Json API

    在.net core 3.0中,内置了一套新的json api,主要用于去除asp.net core对json.net的依赖,同时也提供了更好的性能(直接处理 UTF-8,而无需转码到 UTF-16) ...

  4. C#下的时间测试(用于计算方法执行时间)

    public class Timing { private TimeSpan m_StartTime; private TimeSpan duringTime; public Timing() //构 ...

  5. Git Error:There is no tracking information for the current branch.

    在执行git pull的时候,提示当前branch没有跟踪信息: $> git pull There is no tracking information for the current bra ...

  6. element-ui Upload 上传组件源码分析整理笔记(十四)

    简单写了部分注释,upload-dragger.vue(拖拽上传时显示此组件).upload-list.vue(已上传文件列表)源码暂未添加多少注释,等有空再补充,先记下来... index.vue ...

  7. rem与em的使用和区别详解【转】

    目录 最大的问题是 主要区别  rem 单位如何转换为像素值  em 单位如何转换为像素值 Em 单位的遗传效果 Em 继承的例子 浏览器设置 HTML 元素字体大小的影响 没有设置 HTML 字体大 ...

  8. Nginx03(实现负载均衡)

    一.负载均衡的作用 1.转发功能 按照一定的算法[权重.轮询.Ip_Hash],将客户端请求转发到不同应用服务器上,减轻单个服务器压力,提高系统并发量. 2.故障移除 通过心跳检测的方式,判断应用服务 ...

  9. Delphi-基础(例程、例程返回值)

    一.例程:Delphi中独有的称呼,例程是将具体某个功能的代码进行封装表现形式: 1.过程 2.函数 过程和函数的区别在于有没有返回值二.例程的作用 1.可以解决命名冲突问题 2.提高代码的重复使用率 ...

  10. 函数arguments讲解

         // 总结:1- 函数内部有一个实参 arguments 可以获取所有的实参.      //2- arguments是一个伪数组,如果要使用数组的方法, 将它转为真数组      // 3 ...