从电脑开机加电到main函数的执行【一】

来源:互联网 发布:手机淘宝如何看好评率 编辑:程序博客网 时间:2024/05/21 09:26

最近开始接触操作系统,在用了Linux操作系统这么久,一直不明白他是怎么做到在电脑上运行的?首先我便开始了解了这一问题,即从电脑开机加电到main函数的执行干了什么?

通过自己这几日没事看看书终于了这个过程分了三步,其目的是实现从启动盘加载操作系统程序,完成执行main函数所需要的准备工作。

【第1步】:启动BIOS,准备实模式下的中断向量表和中断服务程序;

【第2步】:从启动盘加载操作系统程序到内存,加载操作系统程序的工作就是利用第1步中准备的中断服务程序实现的;

【第3步】:为执行32位的main函数做过渡工作。

实模式(Real mode)Intel80286和之后的80x86兼容CPU的操作模式。实模式的特性是一个20位的存储器地址空间(2^20=1048576,1MB的存储器可被寻址),可以直接通过软件的方式访问BIOS以及周边硬件,没有硬件支持的分页机制和实时多任务的概念。从80286开始,所有的80x86CPU的开机状态都是实模式;8086等早期的CPU只有一种操作模式,类似于实模式。

计算机的运行时离不开程序的。然而,加电的一瞬间,计算机的内存中,准确的说是RAM中,空空如也,什么程序也没有。硬盘里虽然有操作系统程序,但CPU的逻辑电路被设计为只能运行内存中的程序,它没有能力直接从硬盘运行操作系统。如果要运行硬盘中的操作系统,必须将硬盘中的操作系统程序加载到内存(RAM)中。RAM(Random Access Memory):随机存取存储器。常见的内存条就是一条RAM,它的特点是加电状态下可任意读、写,断电后信息消失。)问题是在RAM中什么程序也没有的时候,谁来完成加载硬盘中操作系统的任务呢?答案便是BIOS

下面我们说说BIOS的启动原理

从我们使用计算机的经验得知:要想执行一个程序,不许再窗口中双击它,或者在命令行界面中输入相应的执行命令。从计算机底层机制上讲,这其实是在一个已经运行起来的操作系统的可视化界面或命令行界面中执行一个程序。但是,在开机加电的一瞬间,内存中什么程序也没有,没有任何程序在运行,不可能有操作系统,更不可能有操作系统的用户界面。我们无法人为地执行BIOS程序,那BIOS程序又是有谁来执行的呢?从体系的角度来看,不难得出这样的结论:既然软件方法不可能执行BIOS,那么就只能靠硬件方法完成了。

从硬件的角度看,Intel80x86系列的CPU可以分别在16位实模式和32位保护模式下运行。为了兼容,也为了解决最开始的启动问题,Intel将所有80x86系列的CPU(包括最新型号的CPU)的硬件都设计为加电即进入16位的实模式状态运行。同时,还有一点非常关键,即将CPU硬件逻辑设计为加电瞬间强行将CS代码段寄存器,指向CPU当前执行代码在内存中所在区域)的值置为0xFFFFIP指令指针寄存器,存在于CPU中,记录将要执行的指令在代码段内的偏移地址。与CS结合便可以指向将要执行的指令内存地址。实模式为绝对地址,指令指针为16位,即IP,保护模式下为32位,即EIP)的值置为0x0000,这样CS:IP就指向0xFFFF0这个地址范围。

然而,上面是一个纯硬件完成的动作!如果此时这个位置没有可执行代码,那么计算机就此死机。反之,如果这个位置有可执行代码,计算机将从这里的代码开始,沿着后续程序一直执行下去。

BOIS程序的入口地址就是0xFFFF0!也就是说,BIOS程序的第一条指令就设计在这个位置上。(各个厂商约定俗成的的东西,不存在位置不同的情况)。

BIOS在内存中加载中断向量表(实模式中断机制的重要组成部分,表中记录了所有中断程序对应的中断服务的内存地址)和中断服务程序(对应中断服务表中的索引的服务程序段

BIOS程序被固化在计算机主板上的一块很小的ROM芯片里。通常,不同的主机板所用的BIOS也有所不同,就启动部分而言,各种类型的BIOS的基本原理大致相似。

CS:IP指向0xFFFFO这个位置的时候,意味着BIOS开始启动了。随着BIOS程序的执行,屏幕上会显示显卡的信息、内存的信息......说明BIOS程序在检测显卡、内存......这期间,有一项对启动(boot)操作系统至关重要的工作,那就是BIOS在内存中建立中断向量表和中断服务程序。

ROM(ReadOnly Memory):只读存储器,现在通常用闪存芯片做ROM。虽然闪存芯片在特定的条件下是可写的,但在谈到主机板上存储BIOS的闪存芯片时,业内人士把它看做ROMROM有一个特性,就是断电之后仍能保存信心,这一点与硬盘类似。

BIOS程序在内存最开始的位置(即:0x00000)1KB的内存空间(0x00000--0x3FF)构建中断向量表,并在紧挨着它的位置用256字节的内存空间构建BIOS数据区(0x00400--0x004FF),在数据区后的某一位加载了与中断向量表相应的若干中断服务程序中断向量表中有256个中断向量,每个中断向量占4个字节,其中两个字节是CS的值,两个字节是IP的值,每个中断向量都指向一个具体的中断服务程序。

执行BIOS程序后,到此,就要开始执行boot操作了,即我们需要将硬盘中的操作系统文件加载到内存。在计算机完成了一系列自检工作后,出于计算机的结构预先设计,BIOS会让CPU接收到一个int 0x19 中断,当CPU接收到这个中断后,会立即在中断向量表中找到int 0x19中断向量,其对应的就是对应的启动加载服务程序,加载硬盘第一扇区的内容到内存。在此需要说的是第一扇区中的程序是由bootsect.s(引导程序)中的汇编程序汇编而成。之后当我们已经把引导程序载入内存时,他的作用就是将之后的第二、三批程序陆续加载到内存,在此之前这个引导程序bootsect首先需要对内存进行规划。这里就需要操作系统的设计者,要全面的整体的考虑内存的规划,确保无论操作系统如何运行都不会出现代码与代码、数据与数据、代码与数据之间的相互覆盖。在实模式下,寻址空间最大为1MBbootsect的代码设计首先就需要对后续操作所涉及的内存位置进行设置,包括要加载的setup程序的扇区数要加载的setup序的扇区数(SETUPLEN)、被加载到的位置(SETUPSEG)、启动扇区被BIOS加载的位置(BOOTSEG)、将要移动到的新位置(INITSEG)、内核被加载的位置(SYSSEG)、内核的末尾位置(SYSEND)、根文件系统设备号(ROOT_DEV)、设置这些位置就是确保将要载入内存的代码和已载入内存的代码以及数据区分,互不覆盖。

内存规划部分还需要复制bootsect以及将setup程序加载到内存。今天就先写到这里,之后的博文会继续对这一问题的阐述。包括之后的加载第三部分代码-----system模块,以及整体过程的最后一步【开始向32位模式转变,为mian函数的调用做准备】。

有什么错误希望指正。

原创粉丝点击