当前位置:   article > 正文

MyOS 之 软盘读取_attempt to reserve non-constant quantity of bss sp

attempt to reserve non-constant quantity of bss space

首先还是采用软盘启动,制作一个软盘镜像,然后用虚拟机装载。

❓为什么不用U盘或者硬盘,现在软盘都淘汰了,为什么不用U盘或者硬盘镜像呢?

因为软盘是基础;软盘1.44MB足够了而且格式清楚。

软盘的大小的组织方式: 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

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

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/346593
推荐阅读
相关标签
  

闽ICP备14008679号