首页 > 代码库 > linux内核设计的艺术--加载内核代码

linux内核设计的艺术--加载内核代码

在BIOS触发0x19中断将磁盘的第一个扇区(512B)加载到内存中后,计算机才真正开始执行磁盘上的程序。而这512B的程序bootsect.s中的第一批代码,此时处理器还处于实模式内存寻址的最大范围是1M(0x0000-0xFFFF),接下来我们看看在bootsect.s的第一批代码中做了些什么?

SYSSIZE = 0x3000                        //内核程序的大小
SETUPLEN = 4				//要加载的setup程序长度单位为扇区数
BOOTSEG  = 0x07c0			//启动扇区被BIOS加载的位置,也就是现在所在的位置
INITSEG  = 0x9000			//bootsect.s即将移动到的位置
SETUPSEG = 0x9020			//setup程序要被加载的开始位置
SYSSEG   = 0x1000			//kernel加载的起始位置
ENDSEG   = SYSSEG + SYSSIZE		//kernel的结束位置
ROOT_DEV = 0x306                        //根文件系统的设备号

上述代码声明了给一系列变量赋值,接下来将在后面的代码中使用他们

entry start
start:
	mov	ax,#BOOTSEG             //
	mov	ds,ax                   //
	mov	ax,#INITSEG             //这段代码是将bootsect的代码从0x07C0
	mov	es,ax                   //复制到0x9020处
	mov	cx,#256                 //
	sub	si,si                   //
	sub	di,di                   //
	rep                             //
<span style="white-space:pre">	</span>movw                            //

因为在后面的程序中,bootsect之前所在的位置会被其他程序覆盖,所以需要将bootsect程序的位置移动


复制完成之后,紧接着执行

	jmpi	go,INITSEG
go:	mov	ax,cs
	mov	ds,ax


这句指令的意思是,跳转到新复制的bootsect处的go继续执行

这个时候,开始加载setup程序到内存中了


load_setup:
	mov	dx,#0x0000		//指定磁头为第0个
	mov	cx,#0x0002		//指定在第2个扇区,第0个磁道
	mov	bx,#0x0200		//setup在磁盘中的物理地址
	mov	ax,#0x0200+SETUPLEN	//指定结束的位置
	int	0x13			//中断读取磁盘
	jnc	ok_load_setup		//加载完成,执行ok_load_setup
	mov	dx,#0x0000
	mov	ax,#0x0000		//重置磁盘
	int	0x13
	j	load_setup

还是老样子,加载setup,只不过这次通过寄存器指定了一系列信息方便中断服务程序访问磁盘


然后调用read_it加载system也就是kernel模块了

	mov	ax,#SYSSEG      //指定system模块加载在内存中的位置
	mov	es,ax		
	call	read_it
	call	kill_motor


到了这一步,bootsect的工作也就算完成了,这时候,内核的代码已经加载到了内存中,但是在离直接执行内核程序的时候还有一段路要走,下一篇将介绍如何为内核代码执行做准备