Boot0的主要作用:
书上说得比较多了,大致的作用就跟MBR差不多,系统安装的时候把它放到硬盘的主引导记录当中,提供一个简单的多操作系统引导功能。如果选择启动FreeBSD,它会在对应的分区里面读“分区引导记录”,也就是Boot1,然后经由Boot1来引导BTX,boot2.bin,最终加载内核。
boot0.s是boot0的源代码,存在两个版本,一个大小是512K,占用一个扇区,还有一个是1024K,占用两个扇区,这两个文件分别是boot0.s,boot0ext.s,存放的目录是:[code]/usr/src/sys/boot/i386/boot0/boot0.s[/code]在boot0.s这个源文件中采用的是AT&T的汇编语言语法格式,在指令上和windows环境下的汇编语言格式略有不同。
一、读这个代码的预备知识:根据PC机的体系结构,硬件启动的最后一个步骤是读取硬盘上的主引导记录,放到内存:0x0000:0x7c00这个地址,一个jmp跳转指令来执行主引导记录的第一条指令。
二、主要的代码:
boot0.s的主要工作流程是
1、代码搬移,从0x7c00这个地址挪到另外一个地址,主要是为了给后续读取分区引导记录boot1腾出空间。
2、扫描分区表,扫描引导扇区有效标志,打印多系统引导界面。
3、根据选择,读取相应分区的分区引导记录
4、出错处理
主要的代码:
1、变量定义:
符号常量定义形式:
2、乾坤大挪移[code]start: cld # String ops inc
xorw %ax,%ax # Zero
movw %ax,%es # Address
movw %ax,%ds # data
movw %ax,%ss # Set up
movw $LOAD,%sp # stack
/*
* Copy this code to the address it was linked for
*/
movw %sp,%si # Source
movw $start,%di # Destination
movw $0x100,%cx # Word count
rep # Relocate
movsw # code[/code]这段代码的作用就是DS:SI内存的数据转移到ES:DI当中,0x200个字节[code]movw $LOAD,%sp # stack[/code]常量的引用:$常量名 $具体的数值
寄存器的使用:%寄存器名
指令格式:
操作码 原操作数,目的操作数 #注释
上面那条指令的作用就是把LOAD的值赋给sp寄存器,也就是这段代码运行期间,栈顶是0x7c00,向下增长。不会影响到0x7c00的代码。[code]movw $start,%di # Destination[/code]start是代码中的标识,实际代表的是代码装载到内存时的地址,因此$start这个引用表示的是地址。
3、中间略去,最后的装载分区引导记录代码:
第312行的main.15[code]main.15:
movw $LOAD,%bx # Address for read
movb $0x2,%ah # Read sector
callw intx13 # from disk
jc main.10 # If error
cmpw $MAGIC,0x1fe(%bx) # Bootable?
jne main.10 # No
movw $crlf,%si # Leave some
callw puts # space
jmp *%bx # Invoke bootstrap[/code]这段代码的作用:使用BIOS系统调用读扇区操作,读取分区引导记录扇区,这里设定是读取FreeBSD分区的分区引导记录boot1,放到DS:BX=0x0000:0x7c00处,如果读取成功,检测读取扇区的最后两个字节,如果成功jmp *%bx
两个寻址方式:[code]cmpw $MAGIC,0x1fe(%bx)[/code]我的理解是:bx(=0x7c00)+0x1fe 把这个数值作为地址,把这个地址内的数值和$MAGIC对比,也就是检测可引导扇区有效标志。[code]jmp *%bx[/code]很显然是无条件跳转到0000:0x7c00处,但是这条指令比较难理解,%bx表示寄存器引用,但是寄存器不能作为jmp的操作数,类似于C语言的做法,用到了地址求值,因为bx=0x7c00,我的理解就是“把BX寄存器的值作为操作数,作为跳转地址”----这种写法很类似C语言。
读boot1.s的代码,可知boot1.s汇编之后的二进制代码和BTX、boot2.bin在安装时是存放在FreeBSD可引导“Silce”中的前16个扇区里面,Jmp $0x7c00,就是运行boot1.s,然后加载BTX,然后运行boot2.c里面的程序,实现内核加载。