您好,欢迎访问三七文档
操作系统引导探究Version0.01前言本篇文章并不旨在完整的讨论一个多引导系统程序怎样去引导不同的操作系统,而只打算从编写操作系统的角度出发,谈谈计算机怎样从加电开始,从无到有,将操作系统运行起来,在其中将尽量详尽的描述从实模式到保护模式的过渡,目的只在于能将所学与广大爱好者更享,为希望开发操作系统的朋友留下一点资料,也为自己留下一点心得。本篇文章将以开发中的pyos系统引导程序为例,pyos是一个正在开发中的实验型操作系统,它并不打算以目前任何一种运行中的操作系统为模式,而只想通过自己编写一个从头到尾的操作系统来学习知识,积累技术,如果你有兴趣,非常欢迎你的加入!本篇纯属学习过程中的一点心得体会,如果你发现其中有错误或不当之处,非常希望你来信指教。一、计算机从加电开始都做了什么?当机算机的电源键被按下时,同这个键相联的电信号线就会送出一个电信号给主板,主板将此电信号传给供电系统,供电系统开始工作,为整个系统供电,并送出一个电信号给BIOS,通知BIOS供电系统已经准备完毕。随后BIOS启动一个程序,进行主机自检,主机自检的主要工作是确保系统的每一个部分都得到了电源支持,内存储器、主板上的其它芯片、键盘、鼠标、磁盘控制器及一些I/O端口正常可用,此后,自检程序将控制权还给BIOS。接下来BIOS读取BIOS设置,得到引导驱动器的顺序,然后依次检查,直到找到可以用来引导的驱动器(或说可以用来引导的磁盘,包括软盘、硬盘、光盘等),然后调用这个驱动器上磁盘的引导扇区进行引导。BIOS是怎么知道或说分辨哪一个磁盘可以用来引导的呢?二、认识引导程序BIOS将所检查磁盘的第一个扇区(512B)载入内存,放在0x0000:0x7c00处(见图三),如果个扇区的最后两个字节是“55AA”,那么这就是一个引导扇区,这个磁盘也就是一块可引导盘。通常这个大小为512B的程序就称为引导程序(boot)。如果最后两个字节不是“55AA”,那么BIOS就检查下一个磁盘驱动器。通过上面的表述我可可以总结出如下三点引导程序所具有的特点:1.它的大小是512B,不能多一字节也不能少一字节,因为BIOS只读512B到内存中去。2.它的结尾两字节必须是“55AA”,这是引导扇区的标志。3.它总是放在磁盘的第一个扇区上(0磁头,0磁道,1扇区),因为BIOS只读第一个扇区。(图一)因此,在我们编写引导程序的时候,我们也必须注意上面的三点原则,符合上面三点原则的程序都可以看作是引导程序,至少BIOS是这样认为的,虽然它也许可能是你随意写的一段并没有什么实际意义的代码。因为BIOS一次只读一个扇区也即512字节的数据到内存中,这显然是不够的,现在操作系统都比较庞大,因此我们必须在引导扇区里将存在磁盘上的操作系统的核心部份读进内存,然后再跳转到操作系统的核心部分去执行。三、通过BIOS读磁盘扇区从上面的描述我们可以知道,引导程序需要将存在于磁盘上的操作系统读入内存,因此这里我们不得不再讲一讲,怎样不通过操作系统(因为现在还没有操作系统)去读磁盘磁区。一般说来这有两种方法可以实现,一种是直接读写磁盘的I/O端口,一种是通过BIOS中断实现。前一种方法是最低层的方法(后一种方法也是在它的基础上实现的),具有极高的灵活性,可以将磁盘上的内容读到内存中的任意地方,但编程复杂。第二种方法是前一种方法稍微高层一点的实现,牺牲了一点灵活性,比如,它不能把磁盘上的内容读到0x0000:0x0000~0x0000:0x03FF处。为什么不能读到此处呢?这里我们将不得不描述一下CPU在加电后的中断处理机制。3.1BIOS的中断处理中断是什么,相信学过计算机的人都不会陌生,如果你对中断一点都不了解建议你翻看一下《计算机组成原理》(高等教育出版社唐朔飞),上面有非常详尽的描述,而一般的汇编教材也多有谈及,因此这里只打算讲讲BIOS对中断的处理。(图二)中断信号中断地址形成部件向量地址0x0000jmp……0x0001jmp……0x0002jmp……0x0003jmp……0x03ffjmp……由上图我们可以清楚的看到,当由中断信号产生时,中断信号通过“中断地址形成部件”产生一个中断向量地址,此向量地址其实就是指向一个实际内存地址的指针,而这个实际内存地址中往往按排一条跳转指令(jmp)跳转到实际处理此中断的中断服务程序中去执行。这一块专门用于处理中断跳转的内存就被称为中断向量表。在内存中这块中断向量表被放在什么地方的呢?而实际的中断处理程序又在什么地方的呢?3.2系统的内存安排(1M)要回答上面的两个问题,我们需要看看系统中内存是怎么安排的。在CPU被加点的时候,最初的1M的内存,是由BIOS为我们安排好了的,每一字节都有特殊的用处。(图三)由上图我们现在可以很方便的问答上面提出的两个问题。由于0x00000~0x003FF是中断向量表所在,因此不能将磁盘从的操作系统读到此处,因为这样会覆盖中断向量表,就无法再通过BIOS中断读取磁盘内容了。你也许会说:我是先调用中断,再读的啊。但事实在BIOS在读的过程中自己会多次调用其它中断辅助完成。3.3利用BIOS13号中断读取磁盘扇区有了前面的描述作为基础,下面我们可以正式描述怎样通过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寄存器:存计数值,表示欲读入的扇区数量在设置了这几个寄存器后,我们就可以使用int13这条指令调用BIOS13号中断读取指定的磁盘扇区,它将磁盘扇区读入ES:BX处,因此,在调用它之前,我们实际上还需要设置ES与BX寄存器,以指出数据在内存中存放的位置。四、保护模式下段模式内存地址的访问写程序离不开对内存的访问,然而在保护模式下内存的访问与在实模式下内存的访问完全不同,这里我们将详细描述一下保护模式下内存的访问方法。当然,这里并不打算完整的介绍保护模式下所有的内存访问方法与机制,只介绍从实模式转到保护模式下所需要进行的转换,完整的内存访问请你最好参见《Intel用户手册》,当然,随着pyos的实验进行,我也会在后面的实验报告与心得体会中渐渐描述,现在不描述主要原因是我还为通过pyos进行实验,对与没经过实验验证的东西,我并不打算也不敢妄下结论,因为在前言中已然说过,这篇文章只是我的一些心得体会,如果我没有实验过,就没有心得,也没有体会,也就无法描述了。言归正转,我们还是先来看看实模式下内存访问方法吧。4.1实模式下的内存访问计算机在加电时,处于“实模式”,在计算机中有一个CR0寄存器,又称为0号控制寄存器,在这个寄存器中,最低位也即第0位,被称为PM(ProtectedModle:保护模式)位,当它被清零的时候表示CPU在“实模式”下工作,当它被置位的时候,表示CPU在“保护模式”下工作。在计算机加电的时候,它是被清零的,所在这个时候的计算机,处于“实模式”。“实模式”下的内存访问通过段寄存器与偏移量构成,比如前面描述中常常出现的0x:0000:0x0001就是一个实模式下的内存地址。分号前面的值表时段寄存器中的值,分号后面的值表是偏移量,实际物理地址的形成如下图所示:(图四)然而在保护模式下,内存地址却不是如上图所示的方法形成的。那么它又时怎样形成的呢?+150段寄存器150偏移量左移4位19020位的物理地址4.2保护模式下的内存地址形成保护模式下内存地址就复杂多了,我们首先要分清三个概念:逻辑地址、线性地址与物理地址。物理地址很好理解,逻辑地址也好理解,就是程序所使用的地址。那么什么是线性地址呢?其实如果不使用分页机制的话,线性地址就是物理地址,它与物理地址是一一对应的,线性地址0,也就是物理地址0。但我们知道,32位的CPU拥有32根地址线,也就是可以访问:322=4GB的内存空间,这实再是一个太大的空间了!现在很少有机器的物理内存能有这么大。那怎么在有限的物理空间中使用4GB的空间呢?人们把物理内存分成许多页,当某些页被使用的时候,某些页就没有被使用,而没有被使用的页就可以用来载入4GB上的空间,这就称为从线性地址到物理地址的映射,这是一个多对一的映射,也就是说多个线性空间中的页对应一个物理空间中的页,希望下面一幅图能有助于你理解这样的分页机制。(图五)上面是一种最简单的映射方式,术语称作“直接相连”映射,它大约只能用来说明问题,而在一个实际的操作系统中通常是“全相联相连”映射,也就是说线性地址中的页可以是映射到物理地址中的任何一个页中,只要那块物理地址空间现在是空闲的。不过,通过上图也能说明问题,当线性地址中的页5需要被访问时,CPU通过地址映射机制将其转换到物理地址,发现其对应物理地址中的页1。于是CPU将物理地址页1中的内容放到硬盘上的一个地方(虚拟内存),然后将线性地址中的页5载入物理内存页1中。这里就当可以比较明显的区别什么是线性地址,什么是物理地址了。然而,当不使用分页机制的时候,线性地址就会被CPU当做物理地址来使用,线性地址会被直接放在CPU的地址信号线上,而在编写应用程序的时候,我们通常使用却是另一种地址——逻辑地址,从逻辑地址到线性地址也存在着与上述机制类似的一种映射机制,不过这个机制常常称为“段模式”,它是由操作系统与CPU硬件共同完成的。操作系统的任务就是分配映射表,而CPU硬件的任务就是按着映射表进行映射。而这样的映射表在操作系统编写中又称之为“描述符表”,有两种重要的描述符表,一种是“全局描述符表(GDT)”,页1页2页3页4页5页1页2页3页4页6页7页8另一种是“局部描述符表(LDT)”,这两种表的用途不同,但它们的用法却是近似的,下面我们就来描述一下全局描述符表。说到表,学过数据结构的人都知道,其实它就是一种数据结构,全局描述符表也是一种数据结构,当这种结构放在一块连续的内存这间中就称之为表了。表由表项组成,全局描述符表由它的表符全局描述符组成,其实单纯的术语就叫“描述符”,只因为它放在全局描述符表中就成了全局描述符了。这个描述符由8个字节组成,下面我们就来看看它的结构:(图六)TYPE:表明此段的类型,4位中的最高位被置1的时候表是它是数据段,相应的于下的三位,从左到右依次为E、W、A,即数据段的TYPE为:0EWA。其中E表示向下增长位,置1时表示向下增长,W表示可写位,置1表洋可定,A表示被访问位(如果CPU访问了它,此位将会被置1)。S:为1时表示其为代码或数据段,为0时表示为系统段DPL:表示物权级,从00~11,共0,1,2,3四个特权级P:为0是表示此描术符无效,不能被使用AVL:留给系统程序随便用的D/B:为0的时候表示它是一个16位的段,为1时表示它是一个32位的段G:为0时,表示段限的单位是1字节,为1时表示段限的单位是4KB,并且段偏移量段基址的0~24位段限的0~15位76543210TYPE:4位S标志:1位DPL标志:3位P标志:1位段限的16~19位AVL标志:1位0:1位D/B标志:1位G标志:1位基址的24~31位的最低12位将不被检测是否在段限之中。(这一点现在可能不好理解,但我下面马上会解释)。这里面有两个部份,比较有意思,一个就是“基址”,一个就是“段限”。基址应当比较好理解,它给出的是一个段在物理内存中的地址,对于“段限”,顾名思义,就是段大小的限制。不过它有
本文标题:操作系统引导探究
链接地址:https://www.777doc.com/doc-5687425 .html