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


kernel,你会发现,上述的动作在DOS中也有类似的对应流程 。;
现在让我们来看看关键的程序码:.;
.;
.;
push#0;
popfs;
movbx,#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:00008A101601F4067000-1600CB04F4067000......p.......p.;
0000:0010F40670000301790E-43EB00F0EBEA00F0..p...y.C.......;
0000:002004108E340C118E34-5700CB046F00CB04...4...4W...o...;
0000:00308700CB0408079433-B700CB04F4067000.......3......p.;
0000:00400C01790E4DF800F0-41F800F0BA165F06..y.M...A....._.;
0000:005039E700F01B01790E-70118E341201790E9.....y.p..4..y.;
0000:006000E000F085175F06-6EFE00F0EE067000......_.n.....p.;
0000:007053FF00F0A4F000F0-220500003E4600C0S......."...>F..;
^^^^^^^^;
由上图中可知,在DOS中磁盘参数表的起始位置(int1Eh的内容)为0000:0522 。接着观察;
DOS中位置0000:0522开始的11个byte,也就是磁盘参数表的内容;
C:>debug;
-d0000:0520l10;
0000:05204D53DF022502121B-FF54F60F08000000MS..%....T......;
^^^^^^^^^^^^^^^^^^^^^^;
此11byte即为磁盘参数表的内容(分别是byte00h到0Ah);
在程序中我们所更动的是第五个byte(byte04h),改为18h(在上图例子中为12h),这;
个byte的功能是定义磁轨上一个磁区的资料笔数 。关键的程序码如下:;
.;
movb4(di),*18;
.;
 ;
第叁步;
接着利用BIOS中断服务int13h的第0号功能,重置磁盘控制器,使得刚才的设定发挥;
功能 。;
.;
.;
xorah,ah;
xordl,dl;
int0x13;
.;
.;
第四步;
完成重置磁盘控制器之后,bootsect就从磁盘上读入紧邻着bootsect的setup程序,;
也就是以后将会介绍的setup.S,此读入动作是利用BIOS中断服务int13h的第2号功能 。;
setup的image将会读入至程序所指定的内存绝对地址0x90200处,也就是在内存中紧邻着;
bootsect所在的位置 。待setup的image读入内存后,利用BIOS中断服务int13h的第8号功;
能读取目前磁盘机的参数 。;
第五步;
再来,就要读入真正linux的kernel了,也就是你可以在linux的根目录下看到的"v;
mlinuz" 。在读入前,将会先呼叫BIOS中断服务int10h的第3号功能,读取游标位置,之;
后再呼叫BIOS中断服务int10h的第13h号功能,在萤幕上输出字符串"Loading",这个字;
符串在bootlinux时都会首先被看到,相信大家应该觉得很眼熟吧 。;
linux的kernel将会被读入至内存绝对地址0x10000处,键关的程序码如下:;
.;
.;
movax,#SYSSEG;
moves,ax;
callread_it;
callkill_motor;
.;
.;
其中SYSSEG于程序开头时定义为0x1000,先将ES内容设为0x1000,接着在read_it这;
个子程序便以ES为目的地的节地址,将kernel读入内存中,至于read_it子程序的详细内;
容笔者并不想一一介绍,不过聪明的读者们应该已经猜到,read_it一定又利用了BIOSi;
nt13h与磁盘有关的I/O中断服务了 。;
至于kill_motor子程序,它的功能在于停止软盘机的马达(各位聪明的读者会不会觉;
得这个子程序的名称取得颇为传神呢?),其程序码如下:;

推荐阅读