《一个操作系统的实现》笔记(4)-- Boot&Loader


一个操作系统从开机到开始运行,大致经历引导->加载内核入内存->跳入保护模式->开始执行内核这样一个过程。
引导扇区(Boot)负责把Loader加载入内存并且把控制权交给它,其它工作放心地交给Loader来做,因为没有512字节的限制,将会灵活得多。

FAT12文件系统

几乎所有的文件系统都会把磁盘划分为若干层次以方便组织和管理,这些层次包括:
- 扇区(Sector):磁盘上的最小数据单元。
- 簇(Cluster):一个或多个扇区。
- 分区(Partition):通常指整个文件系统。

要让引导扇区找到Loader这个二进制文件,并把文件内容全部读出来放进内存里,首先需要了解FAT12的文件格式。

这里存储的都是二进制数据,我们必须要按照FAT12的规范在指定的偏移处填充数据,这样它在读这里的数据时就会现在指定偏移处找到元数据,接着找到真实的数据部分。
FAT12引导扇区的部分格式:

根目录区中的条目格式

很明显,我们在寻找Loader时,只要扫描根目录区这里的条目,发现文件名正确就认为它是我们要找的那个文件,然后根据这个条目的FstClus(它告诉我们文件存放在磁盘的什么位置)字段去数据区找真实的数据内容。
如果文件内容大于512字节(一个扇区),这时候就需要用到FAT表了。
FAT表有两个,FAT2可看做FAT1的备份,它们通常是一样的。
FAT的结构有点像一个位图。每12位称为一个FAT项,从第2项开始表示数据区的每一个簇,FAT项的值代表的是文件的下一个簇号,但如果值大于或等于0xFF8,则表示当前簇已经是本文件的最后一个簇了,所以只需要一直在FAT表里找下去直到最后一个簇号就能把该文件在数据区的所有簇号找到从而读出完整的数据内容。如果值为0xFF7,表示它是一个坏簇。


加载Loader到内存

BIOS中的中断int 13h可以完成读软盘的任务,从而把文件加载到内存中。
从磁盘将数据读入es:bx指向的缓冲区中,每次读出一个簇,直到Loader文件的所有数据都读到缓冲区为止。


向Loader交出控制权

;boot.asm
BaseOfLoader        equ 09000h  ; LOADER.BIN 被加载到的位置 ----  段地址
OffsetOfLoader      equ 0100h   ; LOADER.BIN 被加载到的位置 ---- 偏移地址
;...
    jmp BaseOfLoader:OffsetOfLoader ; 这一句正式跳转到已加载到内
                        ; 存中的 LOADER.BIN 的开始处,
                        ; 开始执行 LOADER.BIN 的代码。
                        ; Boot Sector 的使命到此结束。

这里的org 0100h是什么意思呢?
这段代码在编译阶段就会告诉编译器,将来我们的这段程序要被加载到内存偏移0x100h处的,org没有设置段地址。可以看到OffsetOfLoader正好设置成了0100h。此时程序的指令、数据就以这个偏移为起始点在内存中存放。

;loader.asm
org 0100h
;...具体的loader逻辑

Linux的引导扇区代码Boot.s比我们的要简单许多,它直接把内核移动到目标内存。


你可能感兴趣的:(操作系统)