精选文章 MyOS 之 软盘读取

MyOS 之 软盘读取

作者:才大难为用 时间: 2020-08-05 11:30:47
才大难为用 2020-08-05 11:30:47

首先还是采用软盘启动,qemu实现,把30DayOS的第一天版复制进去即可。这里我选择的是第4天,此时已经构建完毕所有页面了,我需要用nasm汇编重构即可。

软盘的大小的组织方式: 80cylinders x 2heads x 18sectors x 512 bytes

CHS,是FDISK在分区期间所需磁盘信息。

CHS寻址模式将硬盘划分为磁头(Heads)、柱面(Cylinder)、扇区(Sector)。

△磁头(Heads):每张磁片的正反两面各有一个磁头,一个磁头对应一张磁片的一个面。因此,用第几磁 头就可以表示数据在哪个磁面。

△柱面(Cylinder):所有磁片中半径相同的同心磁道构成“柱面",意思是这一系列的磁道垂直叠在一起,就形成一个柱面的形状。简单地理解,柱面数=磁道数。

△扇区(Sector):将磁道划分为若干个小的区段,就是扇区。虽然很小,但实际是一个扇子的形状,故称为扇区。每个扇区的容量为512字节。

② 知道了磁头数、柱面数、扇区数,就可以很容易地确定数据保存在硬盘的哪个位置。也很容易确定硬盘的容量,其计算公式是:

硬盘容量=磁头数2×柱面数80×扇区数18×512字节=1474560字节

一张软盘1440KB,一共有2880个扇区。

一般只有一个软盘驱动器,因此写0(DL)就可以了,然后磁头数(DH,正面用0反面用1,一般都是两个)×柱面数(CH,一圈一圈的,80个,0~79)×扇区数(CL,就是柱面的一个扇区了,18个,1~18)×512字节

实现软盘启动全知晓

 

操作系统之所以认识FAT12格式的磁盘,其秘密就在于逻辑0扇区这512B上。如果这512字节的最后两个字节的内容分别是55和AA(0xAA55低字节在前,高字节在后)的话,BIOS在启动时会将这个扇区读取到0x7C00H~0x7DFFH处,然后跳转到0:7C00h处继续执行指令,操作系统即用此来达到引导系统的目的,而这个磁盘就称为引导磁盘。

操作系统标识FAT12文件系统是因为在逻辑0扇区(即引导扇区)处还存储着一个特定的数据结构,此结构有固定的格式,在操作系统将此磁盘格式化时自动生成(也就是说整个512B都是有特殊规格的),具体数据结构如下表所示:

名称              开始字节    长度      内容                                  参考值 在代码中行号

BS_jmpBOOT          0           3       一个短跳转指令         jmp short LABEL_STARTnop        6

BS_OEMName          3           8       厂商名                                     'ZGH'       7

BPB_BytesPerSec 11              2       每扇区字节数(Bytes/Sector)            0x200        8

BPB_SecPerClus  13              1       每簇扇区数(Sector/Cluster)             0x1        9

BPB_ResvdSecCnt 14              2       Boot记录占用多少扇区                      0x1        10

BPB_NumFATs         16          1       共有多少FAT表                                  0x2        11

BPB_RootEntCnt  17              2       根目录区文件最大数                             0xE0           12

BPB_TotSec16    19              2       扇区总数                                 0xB40          13

BPB_Media           21          1       介质描述符                               0xF0            14

BPB_FATSz16         22          2       每个FAT表所占扇区数                           0x9           15

BPB_SecPerTrk   24              2       每磁道扇区数(Sector/track)              0x12      16

BPB_NumHeads    26              2       磁头数(面数)                           0x2       17

BPB_HiddSec         28          4       隐藏扇区数                                  0            18

BPB_TotSec32    32              4       如果BPB_TotSec16=0,则由这里给出扇区数          0       19

BS_DrvNum           36          1       INT 13H的驱动器号                           0            20

BS_Reserved1    37              1       保留,未使用                             0        20

BS_BootSig          38          1       扩展引导标记(29h)                           0x29          20

BS_VolID            39          4       卷序列号                                   0            21

BS_VolLab           43          11      卷标                                      'ZGH'       22

BS_FileSysType  54              8       文件系统类型                           'FAT12'        23

引导代码         62         448     引导代码及其他数据       引导代码(剩余空间用0填充)         24~42

结束标志0xAA55       510         2  第510字节为0x55,第511字节为0xAA       0xAA55      43

即便是第一行的跳转指令,也是软盘故意设定的。。。

当我们使用了软盘启动系统时,首先会把软盘中第一个扇区(512字节)加载到内存,判断从第510字节开始是否为0xAA55,若是则说明这是一张启动盘,BIOS会开始从0x7C00H进行引导。

0x7C00这个地址来自Intel的第一代个人电脑芯片8088,以后的CPU为了保持兼容,一直使用这个地址。

当时,搭配的操作系统是86-DOS。这个操作系统需要的内存最少是32KB。我们知道,内存地址从0x0000开始编号,32KB的内存就是0x0000~0x7FFF。

8088芯片本身需要占用0x0000~0x03FF,用来保存各种中断处理程序的储存位置。(主引导记录本身就是中断信号INT 19h的处理程序。)所以,内存只剩下0x0400~0x7FFF可以使用。

为了把尽量多的连续内存留给操作系统,主引导记录就被放到了内存地址的尾部。由于一个扇区是512字节,主引导记录本身也会产生数据,需要另外留出512字节保存。所以,它的预留位置就变成了:

  0x7FFF - 512 - 512 + 1 = 0x7C00 

0x7C00就是这样来的。

根据启动时的内存结构,0x7c00 - 0x7dff 用于载入IPL,而0x7e00 - 0x7fff用于引导区运行时栈,因此空闲的应该是从0x8000开始。

因为引导区的代码实在太少了(512字节还用去不少),所以我们需要在其他地方实现boot,这个脚本叫做ipl,方法就是用ipl读取下一个扇区(512字节,也就是boot),在那里读取所有的扇区。

啊不,是一口气装载完所有的,然后算出绝对地址,用ORG固定(实际上它可能什么也不干,就只在list中有用,毕竟文件都是自己复制到内存中去的),查看bin文件也的确是这样的。

ORG(不行,它会出错)

 

关于编译的原理

先用edimg制作出helloos.img,这里用到ipl.bin,参数很多,但是感觉自己也能做,也是蛮清晰的

ipl.bin直接用nask生成

 

我们将剩下的部分拷贝到8200开始的地址,因为boot将启动区放在了7c00,然后磁盘上是没用了,没有临界区的问题,我们把1.44MB的内容复制到0x8000的地址,前512字节被启动区用上了,那么0x8200开始就是真正的程序了(当然启动区需要跳转),

然后在img文件中添加文件,第一个文件的文件名会被放在0x2600的位置,文件的内容会写在4200的位置,然后我们的拷贝到内存中是0x8000位置,所以0x4200处就会在0x8000+0x4200=0xc200位置的地址了。

然鹅我们就是从8200开始存的,因此就跳到8200即可。反正存入内存里谁还管软盘的格式。好好想一想,若从0x800存入数据,存入512个字节,从0开始必然是0x8000-0x81FF,或者0x8001-0x8200。

但是,我为什么,直接拷贝二进制代码呢?毕竟就一个文件,emmmm,实际上,既然前512字节是当作机器码的,后面也应该当作机器码才对。这样是少了16k的,可能是FAT12的问题。

FAT12是DOS时代就开始使用的文件系统(File System),直到现在仍然在软盘上使用,FAT12软盘的被格式化后为:有两个磁头,每个磁头80个柱面(磁道),每个柱面有18个扇区,每个扇区512个字节空间。

2 * 80 *18 * 512=1474560B=1440K=1.44M

FAT12结构图:

1.44M 

        数据区(长度非固定)

xxxx

        根目录区(长度非固定,需要计算)

19*512

18*512

        FAT2

10*512

9*512

        FAT1

512

        引导扇区

0

FAT1和FAT2是两个完全相同的FAT表,每个FAT占用9个扇区。其中FAT1占用1—9扇区,FAT2占用10—18扇区。对于大于512字节的文件,就需要FAT表来寻找该文件占用的所有数据区扇区。那么这里的话就有点问题了呀。但是先不管了

 

根目录区的开始扇区号是19,它是由若干个目录条目(Directory Entry)组成,条目最多有BPB_RootEntCnt个,由于根目录区的大小是依赖于BPB_RootEntCnt的,所以长度不固定。每个条目占32字节,是一个结构体,里面有该文件的属性。

由于根目录区是从第19扇区开始的,每个扇区512个字节,所以其第一个字节位于偏移19*512=9278=0x2600处。

数据区开始的扇区号=根目录区开始的扇区号+14=19+14=33。

第33扇区的偏移量是512*33=16896=0x00004200。

 

现在的首要任务是,用自己的语言写出来启动区的汇编代码。

然后是org到底是怎样的存在?

啊可算明白了,罪魁祸首在最后:

RESB    0x7dfe-$                ; 填写0x00直到0x001fe

如果从0x7c00开始是话,刚好没事,要是从0开始的话,就会陡增至32K的文件。所以必须这么做。

先写一下ml文件吧。

写不了,没意义,只能写一半,但是为了美观容易读,还是建议先优化一下

文件虽然可能大于512字节,但是不用担心,FAT12系统倾向于连续分簇,地址是连续的。

但是软盘格式就很难受了,所以说,你做一个简化版软盘也没什么问题。

毕竟都是整个复制,然后执行代码的那种是吧。

 

这里的ipl10.nas是启动区的汇编代码

asmhead.nas是启动后的设置代码

bootpack.c里面有主函数,naskfunc.nas里面有主函数调用的汇编函数。虽然现在对文件进行文件夹分类还为时尚早,现在先实现汇编化吧。

CYLS    EQU        10 柱面什么用的,而且普通变量定义要放在ORG前面,这样就不会执行到。

首先还是ORG        0x7c00这句话,这句话不能丢,这个是汇编自动推断地址用的。启动区512字节被放到0x7c00位置,然后这段代码将剩下的1MB的内容放到0xc200,然后跳转到那里开始执行。

这里asmhead被放到bootpack之前了,然后一起放到0xc200位置,就是收尾相接的那种。

因此,创建一个1.44MB的空文件,里面每个位都是0.

然后,在前512字节填入ipl代码,直接跳转到512字节处!

然后,将其他所有汇编文件统统编译成一个bin文件,从512字节开始填入这个文件即可。

然后用qemu启动即可。

文件夹为mytool,由于工具可能会迭代,因此最好附在版本里最好了。

nasm -f bin test.asm -o test.bin

这样就会把test.asm编译成纯二进制格式的文件test.bin

然后发现nasm跟nask的语法有不同了。。。

nasm已经不能编译这句命令了
RESB    0x7fe-$            ;
会报错:error: attempt to reserve non-constant quantity of BSS space

解决方法呢,就是把$换成一个固定的值,更好的方法呢,

 

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:打家劫舍系列: 198.打家劫舍 213.打家劫舍2 337.打家劫舍3

下一篇:Goland使用和go问题总结

您可能感兴趣

  • 在Windows Server 2016和SQL Server Always On可用性组上安装SQL Server 2019

    In this article, we will proceed with configuring a SQL Server Always On Availability Groups and perform failover validations. 在本文中,我们将继续配置SQL Server Always On可用性组并执行故障转移验证。 You should go through t...

  • 如何使用损坏或删除SQL Server事务日志文件重建数据库

    This is the last article, but not the least one, in the SQL Server Transaction Log series. In this series of articles (see the TOC below), we described the Transaction Log concept from four differe...

  • 安装SQL Server 2016

    介绍 (Introduction) Microsoft SQL Server 2016 provides faster transactions and queries, deeper insights on any device, advanced analytics, new security technology, and new hybrid cloud scenarios. Alo...

  • JAVA面试(全)

    Java 八大基本数据类型 八大基本类型 Byte,short,long,int,double,float,boolean,char 占用大小及其长度 数据类型 空间(字节B) 取值范围 byte 1 -2^7 ~ 2^7-1 short 2 -2^15~ 2^15-1 char 2 0 ~ 2^16-1 char无需符号位 int 4 -2^31 ~ 2^31-1 float 4 -2^3...

  • SLAM入门+典型SLAM应用及解决方案

    本人初入SLAM小白,目前没有能力发表自己的独到见解,但乐于发现一些好的文章供大家参考,希望对大家有帮助。 随着AR/VR行业的兴起,以及智能移动机器人、无人驾驶的发展,行业对SLAM技术的需求出现了井喷。另一方面,随着传感器技术的发展,计算资源的丰富以及算法的进步,SLAM技术本身也进入了一个从算法到产品过渡的阶段。行业中已经出现了一些以SLAM技术为主的产品,但离进入千家万户还有一定的距...

  • SGX软硬件栈(三)——驱动接口、SGX API

    驱动接口 驱动接口的主要功能还是向不可信运行时uRTS提供管理Enclave生命周期的功能,会在内核权限硬件指令基础之上完成具体的生命周期管理能力。 SGX API 这里将介绍运行时环境(uRTS由Platform Software提供、tRTS由SDK提供)向开发者提供了哪些API供使用。这是SGX开发者直接接触的部分。 1. 可信运行时库函数 由于Enclave程序会被放在Enclave...

  • Lunix下载命令wget

    wget命令 导读: wget是Linux中的一个下载文件的工具,wget是在Linux下开发的开放源代码的软件,作者是Hrvoje Niksic,后来被移植到包括Windows在内的各个平台上。 它用在命令行下。对于Linux用户是必不可少的工具,尤其对于网络管理员,经常要下载一些软件或从远程服务器恢复备份到本地服务器。如果我们使用虚拟主机,处理这样的事务我们只能先从远程服务器下载到我们电...

  • .NET Core代码保护!.NET Reactor这些保护机制你不得不知道!

    .NET Reactor是一个功能强大的代码保护和软件许可系统,适用于为.NET Framework编写的软件,并支持生成.NET程序集的所有语言。 .NET Reactor迎来了久违的版本更新,进入v6.3.0.0全新时代!支持Blazor保护,支持.NET 5 Preview 4保护,允许创建.NET Core 3.x单个文件应用程序,改进了许多功能性能,等等10个功能的更新和改进,还没...

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。