分享
 
 
 

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

王朝system·作者佚名  2008-05-18
窄屏简体版  字體: |||超大  

本文的目的,在将linux kernel的boot部份做一个介绍,因为笔者觉得很少有这样的

文章来介绍一个操作系统最最开始的一步----把kernel本身载入至内存中,同时进行一些

机器相关(machine dependent)的初始化工作,由于linux刚好使用的是大家最熟悉的386,

486系列PC,所以在说明其程序流程时,也刚好可以对其相关的PC硬体架构做探讨,可以

说是一举两得。不过,我必须假设读者对于汇编语言及PC最基础的架构,如寄存器,分段,

分页,中断服务等有大概的认识。

读者可在linux source code的/boot子目录下找到几个以.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的下一行去执行,关键

的汇编代码如下:

.

(搬移bootsect本身)

.

.

jmpi go,INITSEG

go:

.

.

.

表示将跳到CS为0x9000,IP为offset"go"的位置(CS:IP=0x9000:offsetgo),其中

INITSEG=0x9000定义于程序开头的部分,而go这个label则恰好是下一行指令所在的位置。

第二步

接着,将其它segment registers包括DS,ES,SS都指向0x9000这个位置,与CS看齐。

另外将SP及DX指向一任意位移地址(offset),这个地址等一下会用来存放磁盘参数表

(disk parameter table)。

提到磁盘参数表,就必须提到BIOS中断1Eh。先简单地介绍一下BIOS的中断服务:

80x86将内存最低的256*4bytes保留给256个中断向量(每个interrupt vector大小为4bytes,

所以一共有256*4=1024bytes),而其中的第1Eh个向量指向"磁盘参数表",这个表会告诉

电脑如何去读取磁盘机,而我们所要做的事是搬移磁盘参数表到刚才所设定的任意地址。

接着,改变搬移来的参数表的参数,以符合我们的需要。再将中断向量1Eh指向我们

所修改过的磁盘参数表,然后呼叫BIOSinterrupt的int13h(function0,即AH=0)重置磁

盘控制卡及磁盘驱动器,之后磁盘机就会照我们的意思动作了。如果你曾trace过DOS的

kernel,你会发现,上述的动作在DOS中也有类似的对应流程。

现在让我们来看看关键的程序码:.

.

.

push #0

pop fs

mov bx,#0x78

.

(使GS:SI=FS:BX,指向磁盘参数表,

再将GS:SI所指地址的内容搬移6个

word至ES:DI所指的地址)

.

.

此段程序是将FS:BX调整成0000:0078,接着再将GS:SI的内容设成与FS:BX相同,此

处0x78h即为int1Eh的起始位置(7*16+8=120,(1*16+14)*4=120)。调整ES:DI为刚才所设

定的任意地址,从GS:SI搬移6个word(即12byte)到ES:DI所指的位置,显然磁盘参数表的

长度就是6个word,(不过事实上,磁盘参数表的确实长度是11个byte)。关于磁盘参数表,

有兴趣的读者可自行参阅讲述BIOSinterruptservices的技术手册,会有详细的说明。

读者可以用debug自行观察自家机器上dos的磁盘参数表的起始位置(即int1Eh的内容)。

以下是笔者机器的情形(笔者使用的操作系统是msdos6.2):

C:>debug

-d0000:0000

0000:0000

8A101601F4067000-1600CB04F4067000......p.......p.

0000:0010

F40670000301790E-43EB00F0EBEA00F0..p...y.C.......

0000:0020

04108E340C118E34-5700CB046F00CB04...4...4W...o...

0000:0030

8700CB0408079433-B700CB04F4067000.......3......p.

0000:0040

0C01790E4DF800F0-41F800F0BA165F06..y.M...A....._.

0000:0050

39E700F01B01790E-70118E341201790E9.....y.p..4..y.

0000:0060

00E000F085175F06-6EFE00F0EE067000......_.n.....p.

0000:0070

53FF00F0A4F000F0-220500003E4600C0S......."...>F..

^^^^^^^^

由上图中可知,在DOS中磁盘参数表的起始位置(int1Eh的内容)为0000:0522。接着观

察dos中位置0000:0522开始的11个byte,也就是磁盘参数表的内容

C:>debug

-d0000:0520l10

0000:0520

4D53DF022502121B-FF54F60F08000000MS..%....T......

^^^^^^^^^^^^^^^^^^^^^^

此11byte即为磁盘参数表的内容(分别是byte00h到0Ah)

在程序中我们所更动的是第五个byte(byte04h),改为18h(在上图例子中为12h),这

个byte的功能是定义磁轨上一个磁区的资料笔数。关键的程序码如下:

.

movb 4(di),*18

.

第三步

接着利用BIOS中断服务int13h的第0号功能,重置磁盘控制器,使得刚才的设定发挥

功能。

.

.

xor ah,ah

xor dl,dl

int 0x13

.

.

第四步

完成重置磁盘控制器之后,bootsect就从磁盘上读入紧邻着bootsect的setup程序,

也就是以后将会介绍的setup.S,此读入动作是利用BIOS中断服务int13h的第2号功能。

setup的image将会读入至程序所指定的内存绝对地址0x90200处,也就是在内存中紧邻着

bootsect所在的位置。待setup的image读入内存后,利用BIOS中断服务int13h的第8号功

能读取目前磁盘机的参数。

第五步

再来,就要读入真正linux的kernel了,也就是你可以在linux的根目录下看到的

vmlinuz。在读入前,将会先呼叫BIOS中断服务int10h的第3号功能,读取游标位置,之

后再呼叫BIOS中断服务int10h的第13h号功能,在萤幕上输出字符串"Loading",这个字

符串在boot linux时都会首先被看到,相信大家应该觉得很眼熟吧。

linux的kernel将会被读入至内存绝对地址0x10000处,关键的程序码如下:

.

.

mov ax,#SYSSEG

mov es,ax

call read_it

call kill_motor

.

.

其中SYSSEG于程序开头时定义为0x1000,先将ES内容设为0x1000,接着在read_it这

个子程序,便以ES为目的地的节地址,将kernel读入内存中,至于read_it子程序的详细内

容笔者并不想一一介绍,不过聪明的读者们应该已经猜到,read_it一定又利用了BIOS

int13h与磁盘有关的I/O中断服务了。

至于kill_motor子程序,它的功能在于停止软盘机的马达(各位聪明的读者会不会觉

得这个子程序的名称取得颇为传神呢?),其程序码如下:

.

.

kill_motor:

push dx

mov dx,#0x3f2

xor al,al

outb

pop dx

ret

.

.

首先利用DX指定要输出的port,而03f2这个port则是代表了软盘控制器(floppy

disk controller)的所在,再利用outb将资料送出,而我们送出的资料,当然就是归零过的

AL了。如此一来,软盘的马达就停止了。

第六步

接下来做的事是检查root device,之后就仿照一开始的方法,利用indirect jump跳

到刚刚已读入的setup部份,程序码如下:

.

.

jmpi 0,SETUPSEG

其中SETUPSEG已在先前定义为0x9020,所以CS:IP会设定为9020:0000,即跳到绝对

地址为0x90200,也就是setup的起点,而bootsect也大功告成了。

到此为止,内存的内容应该如下图所示:

比较

把大家所熟知的msdos与linux的开机部份做个粗浅的比较,msdos由位于磁盘上

bootsect的boot程序负责把io.sys载入内存中,而io.sys则负有把dos的kernel--

msdos.sys载入内存的重大责任。而linux则是由位于bootsect的bootsect程序负责

把setup及linux的kernel载入内存中,再将控制权交给setup。

至于setup.S,就留到下一次再来讨论了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有