操作系统引导探究
Version 0.01
谢煜波
QQ:13916830
MSN:xieyuboemail@163.com
Email: xieyubo@126.com
网址:http://purec.binghua.com
2004.02
前言
本篇文章并不旨在完整的讨论一个多引导系统程序怎样去引导不同的操作系统,而只
打算从编写操作系统的角度出发,谈谈计算机怎样从加电开始,从无到有,将操作系统运行
起来,在其中将尽量详尽的描述从实模式到保护模式的过渡,目的只在于能将所学与广大爱
好者更享,为希望开发操作系统的朋友留下一点资料,也为自己留下一点心得。
本篇文章将以开发中的 pyos 系统引导程序为例,pyos 是一个正在开发中的实验型操作
系统,它并不打算以目前任何一种运行中的操作系统为模式,而只想通过自己编写一个从头
到尾的操作系统来学习知识,积累技术,如果你有兴趣,非常欢迎你的加入!
本篇纯属学习过程中的一点心得体会,如果你发现其中有错误或不当之处,非常希望
你来信指教。
一、计算机从加电开始都做了什么?
当机算机的电源键被按下时,同这个键相联的电信号线就会送出一个电信号给主板,
主板将此电信号传给供电系统,供电系统开始工作,为整个系统供电,并送出一个电信号给
BIOS,通知 BIOS 供电系统已经准备完毕。随后 BIOS 启动一个程序,进行主机自检,主机
自检的主要工作是确保系统的每一个部分都得到了电源支持,内存储器、主板上的其它芯片、
键盘、鼠标、磁盘控制器及一些 I/O 端口正常可用,此后,自检程序将控制权还给 BIOS。
接下来 BIOS 读取 BIOS 设置,得到引导驱动器的顺序,然后依次检查,直到找到可以用来
引导的驱动器(或说可以用来引导的磁盘,包括软盘、硬盘、光盘等),然后调用这个驱动
器上磁盘的引导扇区进行引导。BIOS 是怎么知道或说分辨哪一个磁盘可以用来引导的呢?
二、认识引导程序
BIOS 将所检查磁盘的第一个扇区(512B)载入内存,放在 0x0000:0x7c00 处(见图三),
如果个扇区的最后两个字节是“55 AA”,那么这就是一个引导扇区,这个磁盘也就是一块
可引导盘。通常这个大小为 512B 的程序就称为引导程序(boot)。如果最后两个字节不是“55
AA”,那么 BIOS 就检查下一个磁盘驱动器。
通过上面的表述我可可以总结出如下三点引导程序所具有的特点:
1. 它的大小是 512B,不能多一字节也不能少一字节,因为 BIOS 只读 512B 到内
存中去。
2. 它的结尾两字节必须是“55 AA”,这是引导扇区的标志。
3. 它总是放在磁盘的第一个扇区上(
0 磁头,0 磁道,1 扇区),因为 BIOS 只读
第一个扇区。
(图一)
因此,在我们编写引导程序的时候,我们也必须注意上面的三点原则,符合上面三点
原则的程序都可以看作是引导程序,至少 BIOS 是这样认为的,虽然它也许可能是你随意写
的一段并没有什么实际意义的代码。
因为 BIOS 一次只读一个扇区也即 512 字节的数据到内存中,这显然是不够的,现在操
作系统都比较庞大,因此我们必须在引导扇区里将存在磁盘上的操作系统的核心部份读进内
存,然后再跳转到操作系统的核心部分去执行。
三、通过 BIOS 读磁盘扇区
从上面的描述我们可以知道,引导程序需要将存在于磁盘上的操作系统读入内存,因
此这里我们不得不再讲一讲,怎样不通过操作系统(因为现在还没有操作系统)去读磁盘磁
区。一般说来这有两种方法可以实现,一种是直接读写磁盘的 I/O 端口,一种是通过 BIOS
中断实现。前一种方法是最低层的方法(后一种方法也是在它的基础上实现的),具有极高
的灵活性,可以将磁盘上的内容读到内存中的任意地方,但编程复杂。第二种方法是前一种
方法稍微高层一点的实现,牺牲了一点灵活性,比如,它不能把磁盘上的内容读到
0x0000:0x0000 ~ 0x0000:0x03FF 处。为什么不能读到此处呢?这里我们将不得不描述一下
CPU 在加电后的中断处理机制。
3.1 BIOS 的中断处理
中断是什么,相信学过计算机的人都不会陌生,如果你对中断一点都不了解建议你翻
看一下《计算机组成原理》(高等教育出版社 唐朔飞),上面有非常详尽的描述,而一般的
汇编教材也多有谈及,因此这里只打算讲讲 BIOS 对中断的处理。
(图二)
中
断
信
号
中断地址形成部件
向
量
地
址
0x0000 jmp ……
0x0001 jmp ……
0x0002 jmp ……
0x0003 jmp ……
0x03ff jmp ……
由上图我们可以清楚的看到,当由中断信号产生时,中断信号通过“中断地址形成部
件”产生一个中断向量地址,此向量地址其实就是指向一个实际内存地址的指针,而这个实
际内存地址中往往按排一条跳转指令(jmp)跳转到实际处理此中断的中断服务程序中去执
行。这一块专门用于处理中断跳转的内存就被称为中断向量表。在内存中这块中断向量表被
放在什么地方的呢?而实际的中断处理程序又在什么地方的呢?
3.2 系统的内存安排(1M)
要回答上面的两个问题,我们需要看看系统中内存是怎么安排的。在 CPU 被加点的时
候,最初的 1M 的内存,是由 BIOS 为我们安排好了的,每一字节都有特殊的用处。
(图三)
由上图我们现在可以很方便的问答上面提出的两个问题。由于 0x00000~0x003FF 是中
断向量表所在,因此不能将磁盘从的操作系统读到此处,因为这样会覆盖中断向量表,就无
法再通过 BIOS 中断读取磁盘内容了。你也许会说:我是先调用中断,再读的啊。但事实在
BIOS 在读的过程中自己会多次调用其它中断辅助完成。
3.3 利用 BIOS 13 号中断读取磁盘扇区
有了前面的描述作为基础,下面我们可以正式描述怎样通过 BIOS 中断读取磁盘扇区
了。要读取磁盘扇区,我们需要使用 BIOS 的 13 号中断,13 号中断会将几个寄存器的值作
为其参数,因此,我们在调用 13 号中断的过程中需要首先设置寄存器。那么当怎样设置寄
存器呢?会用到哪些寄存器呢?请往下看:
0x00000~0x003FF: 中断向量表
0x00400~0x004FF: BIOS数据区
0x00500~0x07BFF: 自由内存区
0x07C00~0x07DFF: 引导程序加载区
0x07E00~0x9FFFF: 自由内存区
0xA0000~0xBFFFF: 显示内存区
0xC0000~0xFFFFF: BIOS中断处理程序区
AH 寄存器:存放功能号,为 2 的时候,表示使用读磁盘功能
DL 寄存器:存驱动器号,表示欲读哪一个驱动器
CH 寄存器:存磁头号,表示欲读哪一个磁头
CL 寄存器:存扇区号,表示欲读的启始扇区
AL 寄存器:存计数值,表示欲读入的扇区数量
在设置了这几个寄存器后,我们就可以使用 int 13 这条指令调用 BIOS 13 号中断读取
指定的磁盘扇区,它将磁盘扇区读入 ES:BX 处,因此,在调用它之前,我们实际上还需要
设置 ES 与 BX 寄存器,以指出数据在内存中存放的位置。
四、保护模式下段模式内存地址的访问
写程序离不开对内存的访问,然而在保护模式下内存的访问与在实模式下内存的访问
完全不同,这里我们将详细描述一下保护模式下内存的访问方法。当然,这里并不打算完整
的介绍保护模式下所有的内存访问方法与机制,只介绍从实模式转到保护模式下所需要进行
的转换,完整的内存访问请你最好参见《Intel 用户手册》,当然,随着 pyos 的实验进行,我
也会在后面的实验报告与心得体会中渐渐描述,现在不描述主要原因是我还为通过 pyos 进
行实验,对与没经过实验验证的东西,我并不打算也不敢妄下结论,因为在前言中已然说过,
这篇文章只是我的一些心得体会,如果我没有实验过,就没有心得,也没有体会,也就无法
描述了。
言归正转,我们还是先来看看实模式下内存访问方法吧。
4.1 实模式下的内存访问
计算机在加电时,处于“实模式”,在计算机中有一个 CR0 寄存器,又称为 0 号控制寄
存器,在这个寄存器中,最低位也即第 0 位,被称为 PM(Protected Modle:保护模式)位,
当它被清零的时候表示 CPU 在“实模式”下工作,当它被置位的时候,表示 CPU 在“保护
模式”下工作。在计算机加电的时候,它是被清零的,所在这个时候的计算机,处于“实模
式”。
“实模式”下的内存访问通过段寄存器与偏移量构成,比如前面描述中常常出现的
0x:0000:0x0001 就是一个实模式下的内存地址。分号前面的值表时段寄存器中的值,分号后
面的值表是偏移量,实际物理地址的形成如下图所示:
(图四)
然而在保护模式下,内存地址却不是如上图所示的方法形成的。那么它又时怎样形成
的呢?
+
15
0
段寄存器
15
0
偏移量
左移 4 位
19
0
20 位的物理地址
评论0