深入分析FreeDos -- 引导代码


好了,下面开始分析boot.bin了,放置在软盘的前512字节中。

如何判断一个软盘是引导软盘呢? 这个任务是交给在BIOS的。

BIOS会读取软盘的前512字节,如果第511个,512个字节的内容为0x55AA,就认定这是个引导软盘,将这512字节放置在内存0x7c00处,并跳转执行。

boot的目的我前一节说过了,就是查找KERNEL.SYS所在软盘位置,将其读到内存中,并跳转执行。

下面是详细细节:

BIOS执行时,设置好了中断向量,boot执行前,内存分布如下:
;	| ROM    |
;	| BIOS   | 0xE000:0000
;	|        |
;	|        |
;	| VGA    |
;	| BIOS   | 0xC000:0000
;	|        |
;	|        |
;	|        |
;	|        |
;	|        |
;	|        |
;	|--------|
;	|BOOT SEC|
;	|ORIGIN  | 07C0:0000
;	|--------|
;	|        |
;	|--------| 0x40:0000
;	|中断向量|
;	|_______ | 0x0:0000

boot会先将自己copy到内存1FE0:7c00处, 0x1FE00+0x7C00=0x27a00 = 158.5K, 即内存偏移158.5K处。

    ;
    mov ax, 0x1FE0    ;目的段地址1FE0
    mov	es, ax
    mov	si, bp        ;bp=0x7C00
    mov	di, bp
    mov	cx, 0x0100    ;copy 256次,每次copy 2个字节,=> copy 512个字节
    rep movsw         

执行完后,内存分布如下:

;	|--------| 2000:0000
;	|BOOT SEC|
;	|RELOCATE|
;	|--------| 1FE0:0000
;	|        |
;	|        |
;	|--------|
;	|BOOT SEC|
;	|ORIGIN  | 07C0:0000
;	|--------|
;	|        |
;	|--------| 0x40:0000
;	|中断向量|
;	|_______ | 0x0:0000

然后如下操作, retf执行后CS=0x1FE0, IP=cont偏移地址,所以下面CPU就在copy过去的boot.bin中执行了

;
    push	es			;	ES=0x1FE0, 压栈
    mov		bx, cont
    push	bx			;	bx=cont的偏移地址, 压栈
    retf				;	retf执行完后,CPU自动将栈中的内容POP给IP,CS

也就是说0x7C00那块的512字节内存已经没有”利用价值了”。

疑问:boot为什么要将自己挪到断地址为1FE0处?
先算下0000:7C00所在的内存偏移:0+0x7C00 = 31KB, 0x7C00之前只有31K的可用内存空间。
boot的目的就是将KERNEL.SYS载入内存,而KERNEL.SYS一般比较大,这个版本的大小约为77KB,
如果从内存开始的地方就放置KERNEL,0x7C00处会被覆盖掉,那boot还怎么执行啊?
所以boot先要将自己挪到内存高处,方便加载KERNEL。

但是目的段不一定必须为1FE0,将其改为3BC0,重新编译运行,也是可以正常加载KERNEL的,可以试试。

剩下的就是读盘,因软盘系统为FAT12格式,所以要找到KERNEL.SYS文件,如前一节所述,要有一段的逻辑代码,先弄懂FAT12格式,再看汇编代码就容易了。

将KERNEL.SYS放到偏移0x60:0000处,然后来个跳转到执行KERNEL代码。

;
%define LOADSEG         0x0060
boot_success:   
	mov     bl, [drive]
	jmp	word LOADSEG:0
疑问:为什么要将KERNEL放到0x600处?
0-0x3FF存放的是中断向量。 0x400-0x5FF 存放BIOS的数据,如当前时间等。
即前面的内容都被占用了,所以KERNEL只能放置在偏移0x600往后的空间了。

在KERNEL执行之前的内容分布如下:
;	| ROM    |
;	| BIOS   | 0xE000:0000
;	|        |
;	|        |
;	| VGA    |
;	| BIOS   | 0xC000:0000
;	|        |
;	|        |
;	|        |
;	|        |
;	|        |
;	|        |
;	|--------|
;	|KERNEL  |
;	|LOADED  |
;	|--------| 0060:0000
;	|        |
;	|--------| 0x40:0000
;	|中断向量|
;	|_______ | 0x0:0000


上篇: 深入分析FreeDos -- Image分析 下篇: 深入分析FreeDos -- KERNEL.MAP