系統(tǒng)運維 一.主引導(dǎo)程序控制權(quán)的轉(zhuǎn)移
首先需要了解的是BootLoader內(nèi)存布局,在嵌入式操作系統(tǒng)中,BootLoader是在操作系統(tǒng)內(nèi)核運行之前運行。可以初始化硬件設(shè)備、建立內(nèi)存空間映射圖,從而將系統(tǒng)的軟硬件環(huán)境帶到一個合適狀態(tài),以便為最終調(diào)用操作系統(tǒng)內(nèi)核準(zhǔn)備好正確的環(huán)境。在嵌入式系統(tǒng)中,通常并沒有像BIOS那樣的固件程序(注,有的嵌入式CPU也會內(nèi)嵌一段短小的啟動程序),因此整個系統(tǒng)的加載啟動任務(wù)就完全由BootLoader來完成。在一個基于ARM7TDMI core的嵌入式系統(tǒng)中,系統(tǒng)在上電或復(fù)位時通常都從地址0x00000000處開始執(zhí)行,而在這個地址處安排的通常就是系統(tǒng)的BootLoader程序。
0x7c00主引導(dǎo)程序的起始地址,之前為??臻g,主要是函數(shù)調(diào)用。,最終主引導(dǎo)程序是從boot程序跳轉(zhuǎn)到0x9000loader,中間部分為Fat表,占用4個字節(jié)
1.通過FAT表加載文件內(nèi)容--流程圖
實驗步驟
1.在虛擬軟盤中創(chuàng)建體積較大的文本文件(Loader)
2.將Loader的內(nèi)容加載到BaseOfLoader地址處
3.打印Loader中的文本(判斷加載是否完全)
org 0x7c00
jmp short start
nop
define:
BaseOfStack equ 0x7c00
BaseOfLoader equ 0x9000
RootEntryOffset equ 19
RootEntryLength equ 14
EntryItemLength equ 32
FatEntryOffset equ 1
FatEntryLength equ 9
header:
BS_OEMName db D.T.Soft
BPB_BytsPerSec dw 512
BPB_SecPerClus db 1
BPB_RsvdSecCnt dw 1
BPB_NumFATs db 2
BPB_RootEntCnt dw 224
BPB_TotSec16 dw 2880
BPB_Media db 0xF0
BPB_FATSz16 dw 9
BPB_SecPerTrk dw 18
BPB_NumHeads dw 2
BPB_HiddSec dd 0
BPB_TotSec32 dd 0
BS_DrvNum db 0
BS_Reserved1 db 0
BS_BootSig db 0x29
BS_VolID dd 0
BS_VolLab db D.T.OS-0.01
BS_FileSysType db FAT12
start:
mov ax, cs
mov ss, ax
mov ds, ax
mov es, ax
mov sp, BaseOfStack
mov ax, RootEntryOffset
mov cx, RootEntryLength
mov bx, Buf
call ReadSector
mov si, Target
mov cx, TarLen
mov dx, 0
call FindEntry
cmp dx, 0
jz output
mov si, bx
mov di, EntryItem
mov cx, EntryItemLength
call MemCpy
mov ax, FatEntryLength
mov cx, [BPB_BytsPerSec]
mul cx
mov bx, BaseOfLoader
sub bx, ax
mov ax, FatEntryOffset
mov cx, FatEntryLength
call ReadSector
mov cx, [EntryItem + 0x1A]
mov si, BaseOfLoader
loading:
mov ax, dx
add ax, 31
mov cx, 1
push dx
push bx
mov bx, si
call ReadSector
pop bx
pop cx
call FatVec
cmp dx, 0xFF7
jnb BaseOfLoader
add si, 512
jmp loading
output:
mov bp, MsgStr
mov cx, MsgLen
call Print
last:
hlt
jmp last
; cx --> index
; bx --> fat table address
;
; return:
; dx --> fat[index]
FatVec:
mov ax, cx
mov cl, 2
div cl
push ax
mov ah, 0
mov cx, 3
mul cx
mov cx, ax
pop ax
cmp ah, 0
jz even
jmp odd
even: ; FatVec[j] = ( (Fat[i+1] & 0x0F) << 8 ) | Fat[i];
mov dx, cx
add dx, 1
add dx, bx
mov bp, dx
mov dl, byte [bp]
and dl, 0x0F
shl dx, 8
add cx, bx
mov bp, cx
or dl, byte [bp]
jmp return
odd: ; FatVec[j+1] = (Fat[i+2] << 4) | ( (Fat[i+1] >> 4) & 0x0F );
mov dx, cx
add dx, 2
add dx, bx
mov bp, dx
mov dl, byte [bp]
mov dh, 0
shl dx, 4
add cx, 1
add cx, bx
mov bp, cx
mov cl, byte [bp]
shr cl, 4
and cl, 0x0F
mov ch, 0
or dx, cx
return:
ret
; ds:si --> source
; es:di --> destination
; cx --> length
MemCpy:
push si
push di
push cx
push ax
cmp si, di
ja btoe
add si, cx
add di, cx
dec si
dec di
jmp etob
btoe:
cmp cx, 0
jz done
mov al, [si]
mov byte [di], al
inc si
inc di
dec cx
jmp btoe
etob:
cmp cx, 0
jz done
mov al, [si]
mov byte [di], al
dec si
dec di
dec cx
jmp etob
done: pop ax
pop cx
pop di
pop si
ret
; es:bx --> root entry offset address
; ds:si --> target string
; cx --> target length
;
; return:
; (dx !=0 ) ? exist : noexist
; exist --> bx is the target entry
FindEntry:
push di
push bp
push cx
mov dx, [BPB_RootEntCnt]
mov bp, sp
find:
cmp dx, 0
jz noexist
mov di, bx
mov cx, [bp]
call MemCmp
cmp cx, 0
jz exist
add bx, 32
dec dx
jmp find
exist:
noexist:
pop cx
pop bp
pop di
ret
; ds:si --> source
; es:di --> destination
; cx --> length
;
; return:
; (cx == 0) ? equal : noequal
MemCmp:
push si
push di
push ax
compare:
cmp cx, 0
jz equal
mov al, [si]
cmp al, byte [di]
jz goon
jmp noequal
goon:
inc si
inc di
dec cx
jmp compare
equal:
noequal: pop ax
pop di
pop si
ret
; es:bp --> string address
; cx --> string length
Print:
mov dx, 0
mov ax, 0x1301
mov bx, 0x0007
int 0x10
ret
; no parameter
ResetFloppy:
push ax
push dx
mov ah, 0x00
mov dl, [BS_DrvNum]
int 0x13
pop dx
pop ax
ret
; ax --> logic sector number
; cx --> number of sector
; es:bx --> target address
ReadSector:
push bx
push cx
push dx
push ax
call ResetFloppy
push bx
push cx
mov bl, [BPB_SecPerTrk]
div bl
mov cl, ah
add cl, 1
mov ch, al
shr ch, 1
mov dh, al
and dh, 1
mov dl, [BS_DrvNum]
pop ax
pop bx
mov ah, 0x02
read: int 0x13
jc read
pop ax
pop dx
pop cx
pop bx
ret
MsgStr db No LOADER ...
MsgLen equ ($-MsgStr)
Target db LOADER
TarLen equ ($-Target)
EntryItem times EntryItemLength db 0x00
Buf:
times 510-($-$$) db 0x00
db 0x55, 0xaa
對此進行make的結(jié)果
從該結(jié)果可以看出,TIME的值為負(fù)數(shù)了,說明主引導(dǎo)程序的大小大于了512,我們需要將其減小,將之前不重要的入棧與出棧的操作進行刪除,以免占用空間,那么我們之前為何要這樣做呢?是為了遵守匯編代碼的約定,有操作相關(guān)寄存器的值就要進行入棧出棧操作。那么我們這塊內(nèi)存已經(jīng)不夠,因此沒必要進行這個操作了。我們將下面的入棧出棧操作進行刪除,但是要在 FindEntry 這個函數(shù)保留 cx 寄存器的入棧出棧的操作,原因是下面不停在改變 cx 寄存器的值。我們在 find 操作中,call MemCmp 操作前后有必要再加上 si 寄存器的入棧出棧操作
將其改正后的make以及在bochs上實現(xiàn)的結(jié)果為會打印loader中的字符串內(nèi)容
B.第一個loader程序
1.起始地址0x9000
2.通過int0x10在屏幕上打印字符串
a.零標(biāo)志位--判斷運算的結(jié)果是否為0,當(dāng)運算結(jié)果為0時,ZF位的值為1
b.同時jxx代表了一個指令族,功能是根據(jù)標(biāo)志位進行調(diào)整
jo當(dāng)OF為1則跳轉(zhuǎn),jc當(dāng)CF為1則跳轉(zhuǎn),jns當(dāng)SF不為1則跳轉(zhuǎn),jz當(dāng)ZF為1則跳轉(zhuǎn),je比較結(jié)果為相等則跳轉(zhuǎn)
loader.asm代碼實現(xiàn)
org 0x9000
begin:
mov si, msg
print:
mov al, [si]
add si, 1
cmp al, 0x00
je end
mov ah, 0x0E
mov bx, 0x0F
int 0x10
jmp print
end:
hlt
jmp end
msg:
db 0x0a, 0x0a
db Hello, D.T.OS!
db 0x0a, 0x0a
db 0x00
將loader.asm進行反編譯得出的結(jié)果
可以看到在這里的jz對應(yīng)的是loader.asm中的je命令
接下來將loader拷貝到軟盤中去,然后從Boot跳轉(zhuǎn)到loader進行執(zhí)行,我們將虛擬軟盤先在linux中進行掛載,然后進行拷貝,最后進行運行
從打印的結(jié)果可以看出,控制權(quán)從boot已經(jīng)轉(zhuǎn)移到loader程序了
將其打印結(jié)果進行修改看在bochs上的實現(xiàn)結(jié)果是否也修改了
在這里我們需要將makefile文件進行修改保證后期的運行簡便
.PHONY : all clean rebuild
BOOT_SRC := boot.asm
BOOT_OUT := boot
LOADER_SRC := loader.asm
LOADER_OUT := loader
IMG := data.img
IMG_PATH := /mnt/hgfs
RM := rm -fr
all : $(IMG) $(BOOT_OUT) $(LOADER_OUT)
@echo Build Success ==> D.T.OS!
$(IMG) :
bximage $@ -q -fd -size=1.44
$(BOOT_OUT) : $(BOOT_SRC)
nasm $^ -o $@
dd if=$@ of=$(IMG) bs=512 count=1 conv=notrunc
$(LOADER_OUT) : $(LOADER_SRC)
nasm $^ -o $@
sudo mount -o loop $(IMG) $(IMG_PATH)
sudo cp $@ $(IMG_PATH)/$@
sudo umount $(IMG_PATH)
clean :
$(RM) $(IMG) $(BOOT_OUT) $(LOADER_OUT)
rebuild :
@$(MAKE) clean
@$(MAKE) all
最后將data.img在window下實現(xiàn)
小結(jié)
1.Boot需要進行重構(gòu)保證在512字節(jié)內(nèi)完成功能
2.在匯編程序中盡量確保函數(shù)調(diào)用前后通用寄存器的狀態(tài)不變
3.Boot成功加載Loader后將控制權(quán)轉(zhuǎn)移
4.Loader程序沒有代碼體積上的限制
網(wǎng)頁題目:操作系統(tǒng)--主引導(dǎo)程序控制權(quán)的轉(zhuǎn)移
分享地址:http://www.rwnh.cn/article38/cpipsp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、網(wǎng)站設(shè)計、微信小程序、全網(wǎng)營銷推廣、商城網(wǎng)站、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)