说明:本文中的内容,主要来自于WB. YANG的一本书,书名《writeos-1.0-2-weekly》,建议看原文,提供链接http://download.csdn.net/detail/mishifangxiangdefeng/5869801
问:文件系统那么大,几行汇编就能完成?
答:需要说明的是,本文并非给操作系统引入文件系统,给操作系统引入文件系统是一项庞大的工作,不是这里的几行汇编就能完成的。
本文是指,给系统所在的软盘引入文件系统。现在的软盘,只是一个系统启动盘。引入文件系统后的软盘,不仅能启动系统,它还可以像一个移动设备一样,被挂载到linux上,并以文件管理的方式使用软盘。
问:既然我们要做的就是一个系统盘,为什么我们要把软盘挂载到linux上,还要往里面放文件呢?
答:目前的启动系统引导盘,仅能加载512字节的内容到内存。如果我们要加载多余512字节的内容,就要自己写代码去load。
第一步:制作软盘系统盘时,把内容放到软盘上。
第二步:启动软盘系统盘时,要找要加载的内容。
第三步:把内容加载到内存。
很显然,我们可以把这些内容,以文件的形式存入、管理和读取。
问:引入文件系统,可以让我们的操作系统突破512字节大小的限制,那么要想突破512字节大小的限制,就一定要引入文件系统呢?
答:不是的。比如《30天自制操作系统》中,就是把内容按顺序存入软盘,然后用的时候也是从头到尾按顺序读取。
顺序存放的优点:方法简单,不用引入文件系统,使用时也不用找要下载的文件。
顺序存放的缺点:扩展性不好,不能管理。比如在中间加一些内容,后面内容的偏移就变了。
权衡利弊,还是引入文件系统。
问:怎样利用系统盘上的文件系统,来突破512字节大小的限制
答:
制件软盘过程:
系统启动过程:
(1)系统自动加载第一个扇区到内存
(2)根据代码,从软盘上找到load.bin
(3)根据代码,加载load.bin到内存
(4)根据代码,将控制权转移到load.bin
问:这些工作具体怎么做?本文将完成哪些工作?
《引入文件系统》:使用FAT12格式化软盘,使软盘不仅可以做系统启动盘,也可以用于用于管理文件
《使用文件系统》:从具有FAT12文件系统的软盘上查找文件,并将文件加载到内容
《测试文件系统》:(1)写一个测试代码,把测试代码做成可执行文件,写入软盘。(2)启动系统后,找到并加载可执行文件到内存。(3)控制权转到测试代码
本文实现的是FAT12文件系统
FAT文件系统存储结构如图所示:
(1) FAT1和FAT2,存储的是文件表项,每一项大小为12ibt,指向固定大小的文件“簇”。如果一个文件包含多个文件簇,表项的内容为文件的下一个簇号。
(2) 根目录,用于根据文件名查找文件的第一个簇。
(3) 数据区。
(4) 存储空间分配的单位是簇,一个簇可以包含一个或多个扇区。在本文中,一个簇包含一个扇区。
所谓引入文件系统,就是具体做法中的第1步,即使用FAT12文件系统对软盘格式化。
所以,先看一下FAT12文件系统的“格式”:
这是一个称为BPB(BIOS Parameter Block)的数据结构。要把它填入到扇区0中,填对了,格式化的工作基本上完成了。
(1) 修改代码
.code16 /*start*/ .text jmp LABEL_START /*Start to boot*/ nop /*nop required*/ /*========================================================================================= Name:FAT12 file system Time:Chapter 2.2 Revision:2 Reason:启动扇区的大小限制为512字节,如果要加载的内容多于512字节,就加不进去了。因此要引入文件系统。让启动扇区将系统控制权转移给文件系统中的某个文件,突破512字节的限制 Method:软盘格式化的过程就是系统把文件系统信息写入到软盘上的过程。 MeMo: FAT文件系统的主要信息,都被提供在前几个扇区内,其中第 0 号扇区尤其重要。在这个扇区内隐藏着一个叫做BPB(BIOS Parameter Block)的数据结构,一旦我们把这个数据结构写对了,格式化过程也基本完成了 以下内容就是对BPB数据结构初始化 =========================================================================================*/ /*Floppy header of FAT12*/ BS_OEMName: .ascii "windmiss" /*OEM String, 8 bytes required*/ BPB_BytsPerSec: .2byte 512 /*Bytes per sector*/ BPB_SecPerCluse: .byte 1 /*Sector per clue*/ BPB_ResvdSecCnt: .2byte 1 /*Reversed sector count*/ BPB_NumFATs: .byte 2 /*Number of FATs*/ BPB_RootEntCnt: .2byte 224 /*Root entries count*/ BPB_TotSec16: .2byte 2880 /*Total sector number*/ BPB_Media: .byte 0xf0 /*Media descriptor*/ BPB_FATSz16: .2byte 9 /*FAT size(sectors)*/ BPB_SecPerTrk: .2byte 18 /*Sector per track*/ BPB_NumHeads: .2byte 2 /*Number of magnetic heads*/ BPB_HiddSec: .4byte 0 /*Number of hidden sectors*/ BPB_TotSec32: .4byte 0 /*If TotSec16 equal 0, this works*/ BS_DrvNum: .byte 0 /*Driver number of interrupt 13*/ BS_Reserved1: .byte 0 /*Reversed*/ BS_BootSig: .byte 0x29 /*Boot signal*/ BS_VolID: .4byte 0 /*Volume ID*/ BS_VolLab: .ascii "Solrex 0.01" /*Volume label, 11 bytes required*/ BS_FileSysType: .ascii "FAT12 " /*File system type, 8 bytes required*/ LABEL_START: /*Initial registers, including ds, es, ss*/ mov %cs, %ax mov %ax, %ds mov %ax, %es call DispStr jmp . /*===================================================================== Routine: DispStr Action: Display a string, string index stored in %dh */ DispStr: mov $MessageLength, %ax mov %ax, %bp #ES:BP = address of string mov $MessageLength, %cx /*String length*/ mov $0x1301, %ax /*ah = 0x13, al = 0x01(W)*/ mov $0x00c, %bx #page number = BH=0, word color = BL = 0x07h mov $0, %dl /*Start row and column*/ int $0x10 #10h is interrupt number ret /*===================================================================== String table */ .set MessageLength, 16 BootMessage: .ascii "Hello, OS world" /*index 0*/ .org 510 #fill 0 in first 510 BYTE .word 0xaa55 #end with 0xaa55, 计算机在发现可启动标识 0xaa55 的时候自动就会做加载工作
(2) Make。
makefile不用修改,make就可以了
对于这一点,我不太明白,make只是做了编译和链接,最后把可执行文件做成。Img,可是又没有执行可执行文件,为什么就起到效果了呢?
将未格式化的boot.img软盘用mount –o loop boot.img mountdir/挂载到目录上,系统会报错。
格式化以后,再mount,就可以成功。
现在把boot.img mount到linux上,就可以把其它的可执行文件放到boot.img中了
p.s. make时候的warning不知道怎么去掉