FreeBSD启动扇区代码分析( 二 )


movw $LOAD,%sp # stack 以上代码:1)首先使用“cld指令清除方向标志,使得以下的进行“rep操作时SI和DI的值递增 。2)使ax清零,并使除代码段cs外的另外两个数据段寄存器es、ds和堆栈段ss清零 。当然,此时cs由于reset或初始上电已经为零了 。3)BIOS已经把引导扇区的512字节的内容读入到了0:0x7c00处,movw $LOAD,%sp 使得堆栈指针指向扇区代码(或曰本段代码 0:0x7c00)的顶部 。虽然堆栈向下生长可能会影响代码的内容,但下面我们马上就把位于0:7c00处代码移到其他地方去执行 。#
# 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把位于0:7c00处的代码搬移到0:0x600处 。注意,此时由于代码连接的重定向,$start=0x600 。#
# Set address for variable space beyond code, and clear it.
# Notice that this is also used to point to the values embedded in the block,
# by using negative offsets.
movw %di,%bp # Address variables
movb $0x8,%cl # Words to clear
rep # Zero
stosw # them通过以上一段代码的执行,本代码已被搬移到0:0x600处,此时si=di=0x600 0x100,以上代码把di的值保存到bp,bp此时指向本程序搬移后的未用的空间的首部,且把此bp所指的16字节空间清零 。以上过程如下图所示:┏>0:0x600 ┏━━━━━┓┃ ┃ ┃┃ ┃搬┃┃ ┃移┃┃ ┃之┃┃ ┃后┃┃ ┃的┃┃ ┃代┃┃ ┃码┃┃ ┃ ┃┃ 0:0x7ff ┣━━━━━┫┃ ┃0 ┃<-bp指向这里(0:0x800),以此开始的16字节被清零 。┃ ┣━━━━━┫以下所称的fake partition entry就是指这里 。┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┣━━━━━┫┃ ┃0 ┃┃ ┗━━━━━┛0:0x7c00 ┏━━━━━┓ ┛ ┃ ┃ ┃搬┃ ┃移┃ ┃之┃ ┃前┃ ┃的┃ ┃代┃ ┃码┃ ┃ ┃0:0x7dff ┗━━━━━┛ 图(二)#
# Relocate to the new copy of the code.
#
incb -0xe(%di) # Sector number
jmp main-LOAD ORIGIN # To relocated code把以上清零的16字节的第二个字节置为1,表示我们已经读取了一个分区 。然后跳转到搬移之后的新代码的main处执行 。#
# Check what flags were loaded with us, specifically, Use a predefined Drive.
# If what the bios gives us is bad, use the '0' in the block instead, as well.
#
main:
testb $0x20,_FLAGS(%bp)# Set number drive?
jnz main.1 # Yes
testb %dl,%dl # Drive number valid?
js main.2 # Possibly (0x80 set)
main.1:
movb _SETDRV(%bp),%dl # Drive number to use上面说过,BIOS把磁盘的引导扇区读入到内存之后,其dl的内容表示启动设备,但我们安装好FreeBSD之后,我们可以改变此引导扇区的内容,其中的一个改变就是可以使我们可以“手动指定我们实际安装FreeBSD的分区,如果我们希望指定FreeBSD所在的boot分区,那么我们在bp-0x45处的位置(即_FLAGS(%bp)处)的bit 0x20置1,那么上面的“movb _SETDRV(%bp),%dl一句中movb_SETDRV(%bp),%dl(即bp-0x46)即指向我们“手动指定FreeBSD所在分区代码,例如,IDE的C、D盘(严格来说是第一个物理磁盘的第一个和第二个分区)的代码分别为 0x80和0x81 。如果没有“手动指定启动分区,那么,我们缺省使用机器当前启动的分区,上面说过,机器当前启动的分区代码放在dl中 。因为FreeBSD Boot Manager 不可能安装到软盘(如果从软盘启动则dl为0),所以,使用testb %dl,%dl来判断驱动器代码是否合法(volid) 。有关_FLAGS(%bp)中其他bit位表示的意义,在随后的代码分析中慢慢给你道来 。#

推荐阅读