您的位置:首页 > 运维架构 > Linux

Linux0.11内核--引导程序分析

2016-05-27 18:09 507 查看
1.简介

本文主要介绍三个文件bootsect.s、setup.s、head.s,主要是做了些从软盘加载内核和设置32位保护模式的操作。

2.程序分析

当PC电源打开后,BIOS自检后将bootsect读入内存绝对地址0x7c00处,因为bootsect.s的结尾是:

.word 0xAA55


然后跳转到0x7c00处并把执行权交给此处的代码,从start:处开始执行。

BOOTSEG  = 0x07c0
INITSEG  = 0x9000

start:
mov	ax,#BOOTSEG
mov	ds,ax
mov	ax,#INITSEG
mov	es,ax
mov	cx,#256
sub	si,si
sub	di,di
rep
movw
jmpi	go,INITSEG


BOOTSEG是当前程序的起始内存地址的段地址,INITSEG表示是bootsect将要移动要的内存地址的段地址,这段代码的意思是重复执行movw指令256次,每次从BOOTSEG(0x7c0段地址)+si的地址处移动一个字(2个字节)的数据到INITSEG(0x9000段地址)+di地址处,挨个移动256次,所以总共就是256字(512字节),bootsect.s编译出来也就是512字节的大小。所以这段代码执行完之后就是把自己拷贝到0x90000地址处,然后jmpi跳转到0x9000的偏移地址为go的地方执行。

所以接下来程序执行到go:处,但是整个程序的起始段地址变成了0x9000,go处的代码设置了下堆栈,接着是load_setup:

SETUPLEN = 4

load_setup:
mov	dx,#0x0000		! drive 0, head 0
mov	cx,#0x0002		! sector 2, track 0
mov	bx,#0x0200		! address = 512, in INITSEG
mov	ax,#0x0200+SETUPLEN	! service 2, nr of sectors
int	0x13			! read it
jnc	ok_load_setup		! ok - continue
mov	dx,#0x0000
mov	ax,#0x0000		! reset the diskette
int	0x13
j	load_setup


利用BIOS中断int 0x13将setup从磁盘第2个扇区开始读到0x90200开始处,共SETUPLEN(setup 程序的扇区数)读4个扇区。成功后跳转到ok_load_setup。

SETUPSEG = 0x9020

ok_load_setup:
...
mov	ax,#SYSSEG
mov	es,ax		! segment of 0x010000
call	read_it
call	kill_motor

...
jmpi	0,SETUPSEG


省略的代码都是一些读硬盘和驱动器的数据。这里比较关键的是call read_it,调用read_it:

SYSSIZE = 0x3000
SYSSEG   = 0x1000
ENDSEG   = SYSSEG + SYSSIZE

read_it:
mov ax,es
test ax,#0x0fff
die:	jne die			! es must be at 64kB boundary
xor bx,bx		! bx is starting address within segment
rp_read:
mov ax,es
cmp ax,#ENDSEG		! have we loaded all yet?
jb ok1_read
ret
ok1_read:
...


SYSSIZE是编译后system模块的大小,SYSSEG是system模块将加载到的内存段地址处,所以ENDSEG的值就是system模块停止加载的段地址。那么read_it的作用就是先判断一下es是不是到了system模块停止加载的段地址处,如果没有则跳转去读取system模块到这个地址。加载完成后就ret返回。然后关闭马达后读一些驱动器的信息,最后jmpi 0,SETUPSEG跳转到0x9020:0000也就是setup.s程序的开始处。

bootsect.s就此结束,到现在为止内核各个模块在内存中的位置如下图的第3步:



接下来进入setup.s。

未完待续
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: