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在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這段代碼的作用就是DS:SI內存的數據轉移到ES:DI當中,0x200個字節
CODE:movw $LOAD,%sp # stack常量的引用:$常量名 $具體的數值
寄存器的使用:%寄存器名
指令格式:
操作碼 原操作數,目的操作數 #注釋
上面那條指令的作用就是把LOAD的值賦給sp寄存器,也就是這段代碼運行期間,棧頂是0x7c00,向下增長。不會影響到0x7c00的代碼。
CODE:movw $start,%di # Destinationstart是代碼中的標識,實際代表的是代碼裝載到內存時的地址,因此$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這段代碼的作用:使用BIOS系統調用讀扇區操作,讀取分區引導記錄扇區,這裡設定是讀取FreeBSD分區的分區引導記錄boot1,放到DS:BX=0x0000:0x7c00處,如果讀取成功,檢測讀取扇區的最後兩個字節,如果成功jmp *%bx
兩個尋址方式:
CODE:cmpw $MAGIC,0x1fe(%bx)我的理解是:bx(=0x7c00)+0x1fe 把這個數值作為地址,把這個地址內的數值和$MAGIC對比,也就是檢測可引導扇區有效標志。
CODE:jmp *%bx很顯然是無條件跳轉到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裡面的程序,實現內核加載。