Linux开机过程的分析(关于bootsect.S)

本文的目的,在于将linux kernel的boot部分做一个介绍,因为笔者觉得很少有这样的 文章来介绍一个操作系统最最开始的一步----把kernel本身载入至内存中,同时进行一些 机器相关(machine dependent)的初始化工作,由于linux刚好使用的是大家最熟悉的386, 486系列PC,所以在说明其程序流程时,也刚好可以对其相关的PC硬体架构做探讨,可以 说是一举两得。不过,我必须假设读者对于汇编语言及PC最基础的架构,如寄存器,分段, 分页,中断服务等有大概的认识。
  读者可在linux source code的linux/arch/i386/boot子目录下(本文以2.2.5版本为例)找到几个以.S作为副档名的组合语言档, 本文要说明的即是其中的bootsect.S及setup.S两个档案,及尽量简单地说明其所牵涉的 相关硬件部份。
bootsect.S
  这个程序是linux kernel的第一个程序,包括了linux自己的bootstrap程序,但是 在说明这个程序前,必须先说明一般IBM PC开机时的动作(此处的开机是指"打开PC的电源"):
  一般PC在电源打开时,是由内存中地址FFFF:0000开始执行(这个地址一定在ROMBIOS 中,ROMBIOS一般是在FE000h到FFFFFh中),而此处的内容则是一个jump指令,jump到另 一个位于ROMBIOS中的位置,开始执行一系列的动作,包括了检查RAM,keyboard,显示 器,软硬磁盘等等,这些动作是由系统测试码(system test code)来执行的,随着制作 BIOS厂商的不同而会有些许差异,但都是大同小异,读者可自行观察自家机器开机时, 屏幕上所显示的检查讯息。
  紧接着系统测试码之后,控制权会转移给ROM中的启动程序(ROM bootstrap routine), 这个程序会将磁盘上的零道零扇区读入内存中(这就是一般所谓的bootsect,如果你曾 接触过电脑病毒,就大概听过它的大名),至于被读到内存的哪里呢?----绝对位置07C0 :0000(即07C00h处),这是IBM系列PC的特性。而位在linux开机磁盘的bootsect上的正 是linux的bootsect程序,也就是说,bootsect是第一个被读入内存中并执行的程序。 现在,我们可以开始来看看到底bootsect做了什么。

第一步
 
  首先,bootsect将它"自己"从被ROMBIOS载入的绝对地址0x7C00处搬到0x90000处, 然后利用一个jmpi(jumpindirectly)的指令,跳到新位置的jmpi的下一行去执行,关键 的汇编代码如下:
! ld86 requires an entry symbol. This may as well be the usual one.
.globl    _main
_main:
#if 0
    int    3
#endif
    mov    ax,#BOOTSEG                 // BOOTSEG=0x07C0
    mov    ds,ax
    mov    ax,#INITSEG                   //  INITSEG=0x9000
    mov    es,ax
    mov    cx,#256                            // cx寄存器用作计数器
    sub    si,si
    sub    di,di
    cld               //    CLD(CLear Direction flag)则是清方向标志位,也就是使DF的值为0,
                        //    在执行串操作时,使地址按递增的方式变化,这 样便于调整相关段的的当前指针。
                        //    这条指令与STD(SeT Direction flag)的执行结果相反,即置DF的值为1。
    rep              //     MOVSB(MOVe String Byte):即字符串传送指令,这条指令按字节传送数据。
                        //       通过SI和DI这两个寄存器控制字符串  的源地址和目标地址,比如DS:SI这段地址的N个字节
                         //     复制到ES:DI指向的地址,复制后DS:SI的内容保持不变。 而REP(REPeat)指令就是“重复”的意思,
          

你可能感兴趣的:(linux源码分析)