- 論壇徽章:
- 0
|
當(dāng)PC加電自檢完成后,會自動在磁盤第一個(gè)扇區(qū)的最后兩個(gè)字節(jié)查找是否存在標(biāo)識數(shù)0xAA55。如果存在,BIOS會將該扇區(qū)加載到內(nèi)存的0x7C00處,并執(zhí)行其代碼。
masterboot.s文件存放在源代碼樹的boot目錄中,其編譯好的二進(jìn)制代碼會被放置在硬盤的MBR中,在系統(tǒng)引導(dǎo)時(shí)執(zhí)行以下操作:如果是通過硬盤引導(dǎo),且該硬盤的一個(gè)分區(qū)被設(shè)置成為活動分區(qū),則從該活動分區(qū)引導(dǎo);否則,查找下一塊硬盤,直到成功。對該文件的源代碼分析如下:
LOADOFF = 0x7C00 ! 本段代碼被加載的地址
BUFFER = 0x0600 ! 第一塊空閑內(nèi)存空間
PART_TABLE = 446 ! 分區(qū)表位置
PENTRYSIZE = 16 ! 分區(qū)表項(xiàng)大小
MAGIC = 510 ! 標(biāo)識數(shù)0xAA55的位置
bootind = 0
sysind = 4
lowsec = 8
.text
! 尋找活動分區(qū),載入其第一個(gè)分區(qū)并運(yùn)行之
master:
! 將ax、ds、es、ss置0,將LOADOFF載入sp
xor ax, ax
mov ds, ax
mov es, ax
cli ! 關(guān)中斷
mov ss, ax
mov sp, #LOADOFF
sti ! 開中斷
! 將從ds:si(0x0000:0x7C00)開始的512個(gè)字節(jié)拷貝到es:di(0x0000:0x0600)
mov si, sp ! 將0x7C00裝入si
push si ! 將si(即0x7C00)壓棧
mov di, #BUFFER
mov cx, #512/2
cld
rep movs
jmpf BUFFER+migrate, 0 ! 遠(yuǎn)跳轉(zhuǎn)到拷貝后的migrate處開始執(zhí)行
migrate:
! 查找活動分區(qū)
findactive:
testb dl, dl ! 如果dl最高位為0(即不存在引導(dǎo)分區(qū))
jns nextdisk ! 則跳轉(zhuǎn)到nextdisk
mov si, #BUFFER+PART_TABLE ! 將分區(qū)表地址保存到si中
find: cmpb sysind(si), #0 ! 如果該分區(qū)未使用則跳轉(zhuǎn)到nextpart
jz nextpart
testb bootind(si), #0x80 ! 如果不是引導(dǎo)分區(qū)則跳轉(zhuǎn)到nextpart
jz nextpart
loadpart:
call load ! 載入bootstrap
jc error1 ! 錯(cuò)誤處理
bootstrap:
ret ! 跳轉(zhuǎn)到載入的bootstrap執(zhí)行
nextpart:
! 檢查下一個(gè)分區(qū),如果不存在引導(dǎo)分區(qū)則顯示錯(cuò)誤信息并跳轉(zhuǎn)到reboot
add si, #PENTRYSIZE
cmp si, #BUFFER+PART_TABLE+4*PENTRYSIZE
jb find
call print
.ascii "No active partition\0"
jmp reboot
! 該磁盤上沒有活動分區(qū),查找下一塊磁盤
nextdisk: incb dl
testb dl, dl
js nexthd ! dl最高位為1(為硬盤)則跳轉(zhuǎn)到nexthd
int 0x11 ! 將軟驅(qū)數(shù)量保存到ah中
shl ax, #1
shl ax, #1
andb ah, #0x03
cmpb dl, ah ! 如果dl大于ah則跳轉(zhuǎn)到nextdisk
ja nextdisk
call load0 ! 嘗試讀取bootstrap
jc nextdisk ! CF=1(即讀取失。﹦t跳轉(zhuǎn)到nextdisk
ret ! 返回程序開始處執(zhí)行
nexthd: call load0 ! 讀取硬盤的bootstrap
error1: jc error ! 錯(cuò)誤處理
ret
! 從第一個(gè)扇區(qū)中讀取bootstrap
load0:
mov si, #BUFFER+zero-lowsec
load:
mov di, #3 ! 進(jìn)行三次嘗試
retry: push dx
push es
push di
movb ah, #0x08 ! 讀取dl(最高位為1表示為硬盤)指定的磁盤的參數(shù)
int 0x13
pop di
pop es
andb cl, #0x3F ! 在cl中保存每磁道扇區(qū)數(shù)
incb dh ! 在dh中保存每柱面磁頭數(shù)
movb al, cl
mulb dh ! 在bx中保存每柱面扇區(qū)數(shù)(磁頭數(shù)*扇區(qū)數(shù))
mov bx, ax
mov ax, lowsec+0(si) ! 在dx:ax中保存磁盤的總扇區(qū)數(shù)(即地址為zero的變量)
mov dx, lowsec+2(si)
cmp dx, #[1024*255*63-255]>>16 ! 如果分區(qū)超過8G則跳轉(zhuǎn)到bigdisk
jae bigdisk
%3
本文來自ChinaUnix博客,如果查看原文請點(diǎn):http://blog.chinaunix.net/u/27624/showart_259225.html |
|