操作系统——让操作系统走进保护模式

操作系统——让操作系统走进保护模式

实验内容:

  1. 向软盘镜像文件写入一个你指定的文件,手工读取在磁盘中的信息
  2. 在软盘中找到指定的文件,读取其扇区信息
  3. 将指定文件装入指定内存区,并执行
  4. 学会在bochs中使用xxd读取反汇编信息

实验环境:

Ubuntu32位 + VMware Workstation

实验步骤:

  1. 向软盘镜像文件写入一个你指定的文件,手工读取在磁盘中的信息
  2. 在软盘中找到指定的文件,读取其扇区信息
  3. 将指定文件装入指定内存区,并执行
  4. 学会在bochs中使用xxd读取反汇编信息

实验的问题以及解决:

1.FAT12格式是怎样的?

操作系统——让操作系统走进保护模式_第1张图片
其中,引导扇区的格式为:
操作系统——让操作系统走进保护模式_第2张图片
引导扇区中决定了磁盘的基本信息,是FAT12格式的核心。

2.如何读取一张软盘的信息

要想读取软盘信息,最好的方法就是读取它的引导扇区。
引导扇区是软盘的第一个扇区,其中每个字节都有其对应的含义,结束标志为0xAA55。可以通过linux的xxd指令查看其内容。
Xxd的帮助文档如下:
操作系统——让操作系统走进保护模式_第3张图片

查看a.img结果如下:
操作系统——让操作系统走进保护模式_第4张图片
将其中不同字节的含义进行区分,就能得到软盘的信息。

3.如何在软盘中找到指定的文件

由于我们知道,FAT12文件系统存在FAT表和根目录,也就是说每一个文件的信息应该是被存储在这两个目录表中的,所以我们可以在表中查找文件的信息,之后根据表中的扇区号、簇号和偏移信息来查看文件内容。
操作系统——让操作系统走进保护模式_第5张图片
在这里插入图片描述
在上图中,我在a.img这个软盘中插入了一个文件叫river.txt,可以看到,在根目录中存放了其信息,包括文件名称等,我们主要注意的是偏移为0x1A,长度为2的内容,含义为此条目对应的开始簇号。由于在这个文件系统中我们设置的是一个扇区对应一个簇,所以簇和扇区其实差不多。
可以看到,在这个例子里,开始簇号为0x0003,即3。也就是对应着数据区的3号簇。
根据定义,数据区开始扇区号 = 根目录区开始扇区号 + 14 = 33,但开始扇区号为2,我们是3号簇,所以我们的偏移为:
512 * 34 = 0x4400
在这里插入图片描述
找到啦!

4.如何在系统引导过程中,从读取并加载一个可执行文件到内存,并转交控制权?

读取,加载并转交 共有三步,我们一步一步分析。

读取:
首先需要从磁盘扇区中,找到可执行文件的位置。算法思路比较清晰,就是遍历更目录区所有的扇区,将每一个扇区加载入内存,然后从中寻找文件名为Loader.bin的条目。找到的那一刻,es:di是指向条目中字母N后面的那个字符。
操作系统——让操作系统走进保护模式_第6张图片
操作系统——让操作系统走进保护模式_第7张图片
当找到之后,代码停在死循环位置,即114行。
我们在bochs中debug一下这个程序,在此之前别忘了把Loader.bin文件放入软盘。
操作系统——让操作系统走进保护模式_第8张图片
由于我们没有对这个程序的结尾进行什么输出,所以我们需要使用debug来观察是否匹配成功。
操作系统——让操作系统走进保护模式_第9张图片
下断点,跳过BPB,查看此时的反汇编程序:
操作系统——让操作系统走进保护模式_第10张图片
也就是说在0x7cad位置为程序死循环位置,我们在这里下一个断点,并查看es:di前后的内容。
操作系统——让操作系统走进保护模式_第11张图片
这样看起来不太直观,我们直接查看字符内容:
操作系统——让操作系统走进保护模式_第12张图片
看到了我们的文件名,此时继续查看当前寄存器es 和 di的值:
操作系统——让操作系统走进保护模式_第13张图片
表示内存0x9012b处,说明我们成功找到了这个文件。

**加载:**找到之后,根目录区对我们就失去了作用,所以为了简化实验,我们直接选择将Loader程序覆盖在这个区域,也就是加载到BaseOfLoader:OffsetOfLoader处。装入扇区对我们来说并不复杂,但从FAT中找到一个项还是需要经过计算的。而且如果Loader较大,占用多个扇区的话,我们需要反复从FAT中找相应的项,所以我们使用一个函数来完成。
操作系统——让操作系统走进保护模式_第14张图片
红框画出来的是区别对待扇区号是奇数还是偶数。
计算FAT的值的算法为:偏移 + SectorNoOfFAT1(FAT1的第一个扇区号)
偏移 = FATEntry所在的扇区相对于FAT的扇区号。(因为FAT不止占用一个扇区)
需要注意的是,由于一个FAT项可能跨越两个扇区,所以总是一次读取两个扇区。
下面开始加载:
操作系统——让操作系统走进保护模式_第15张图片
首先理解为什么要有一个宏变量叫DeltaSectorNo。由于数据区的第一扇区号为2,所以在从FAT中获取了偏移量X之后,我们需要用 “X+RootDirSectors+19-2”来算出正确扇区号,我们将19-2=17定义为DeltaSectorNo,来简化代码篇幅。
上述程序将文件内容加载到内存中,结束条件如红框2所示,结束之后打印字符串“Ready.”

**移交控制权:**怎样才算移交控制权呢?那当然是看他有没有成功输出啦:
在这里插入图片描述
成功!
如果将pmtest9.asm编译之后的文件命名为loader.bin,也是可以运行的:
在这里插入图片描述

5.为什么需要这个Loader程序不包含dos系统调用?

我们设计Loader程序的初衷是来完成 引导->加载内核入内存->跳入保护模式->开始执行内核 的前三步,也就是说此时我们的操作系统内核并没有开始运行,所以Loader程序是不可能包含dos系统调用的,因为此时的dos都没准备好呢!

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