2.1 計算機的啟動過程
載入內存:
(1) 程序被加載器(軟件或硬件)加載到內存某個區域
(2)CPU 的 cs:ip 寄存器被指向這個程序的起始地址
2.2 軟件接力第一棒,BIOS
2.2.1 實模式下的 1MB 內存布局
Intel 8086 有 20 條地址線,故其可以訪問 1MB 的內存空間,即2的20次方=1048576=1MB。
實模式下的內存布局如下:
(1)在電腦未開機前,BIOS就被事先寫入到內存的F0000~FFFFF中,此區域為ROM,這里面存的是 BIOS 的代碼。BIOS的主要工作是檢測、初始化硬件,建立中斷向量表。
(2)除了內存條,還有一些外設同樣是需要通過地址總線來訪問。
2.2.2 BIOS 是如何蘇醒的
在開機的一瞬間,CPU的cs:ip
寄存器被強制初始化為0xF000: 0xFFF0
,由于開機的時候處于實模式,按照實模式的尋址方式段基地址要乘以16,也就是左移4位,然后再加上段內偏移地址,則計算得這個實際的物理地址為0xFFFF0
,此地址便是BIOS程序的入口地址。而從地址0xFFFF0~0xFFFFF
只有16B的空間,這說明BIOS真正的執行腳本并不存儲在這里,開機后執行的第一條語句一定是跳轉語句jmp
,其實執行的第一條語句是:
jmp far f000:e05b
跳轉到了0xfe05b
處,說明這里才是BIOS代碼真正開始的地方。接下來就是BIOS不斷進行檢測內存,顯卡等外設信息,然后初始化硬件的過程了。
2.2.3 為什么是 0x7c00
BIOS 最后一項工作校驗啟動盤中位于0盤0道1扇區的內容。如果此扇區末尾的兩個字節分別是魔數0x55
和0xaa
,BIOS便認為此扇區中確實存在可執行的程序,并把這個扇區的內容加載到物理地址0x7c00
的內存中。
2.3 實驗
任務:
(1)完成mbr主引導記錄的代碼編寫,并完成編譯,完成的代碼編譯并非真正的MBR主引導程序,而是為了測試mbr程序是否會被加載到0x07c00處被正確執行。
(2)將編譯生成的主引導記錄內容刻錄到我們的創建的啟動硬盤中。
創建mbr.s文件:
(1)文件功能:在屏幕上打印字符串“1 MBR”,背景色為黑色,前景色(字體顏色)為綠色.
(2)功能實現方式:借助BIOS建立好的例程0x10號中斷,可將0x10號中斷看做一個函數,這個函數不同的輸入可實現不同的功能,因此要有一個參數表示要實現的功能,也就是接下來要說的功能號參數。
代碼:
; ~/d2los/src/mbr.S
; MBR主引導程序
;------------------------------------------------------------
SECTION MBR vstart=0x7c00 mov ax,cs mov ds,axmov es,axmov ss,axmov fs,axmov sp,0x7c00; 清屏利用 0x06號功能, 上卷全部行, 實現清屏
; -----------------------------------------------------------
; INT 0x10 功能號: 0x06 功能描述: 上卷窗口
; ------------------------------------------------------
; 輸入:
; AH = 功能號 0x06
; AL = 上卷的行數(如果為0, 表示全部)
; BH = 上卷行屬性
; (CL, CH) = 窗口左上角的(X, Y)位置
; (DL, DH) = 窗口右下角的(X, Y)位置
; 無返回值mov ax, 0x600mov bx, 0x700mov cx, 0 ; 左上角: (0, 0)mov dx, 0x184f ; 右下角: (80, 25),; VGA文本模式中, 一行只能容納80個字符, 共25行.; 下標從0開始, 所以0x18=24, 0x4f=79int 0x10 ; int 0x10; 獲取光標位置
; -----------------------------------------------------------
; .get_cursor 獲取當前光標位置, 在光標位置處打印字符.mov ah, 3 ; 輸入: 3號子功能是獲取光標位置, 需要存入ah寄存器mov bh, 0 ; bh寄存器存儲的是要獲取光標的頁號int 0x10 ; 輸出: ch=光標起始行, cl=光標結束行; dh=光標所在行號, dl=光標所在列號; 獲取光標位置結束
; -----------------------------------------------------------; 打印字符串
; -----------------------------------------------------------
; 還是用10h中斷, 不過這次是調用13號子功能打印字符串mov ax, message mov bp, ax ; es:bp 為字符串起始地址, es此時同cs一致,; 開始時已經為sreg初始化; 光標位置要用到dx寄存器中的內容, cx中的光標位置可忽略mov cx, 5 ; cx 為字符串長度, 不包括結束符0的字符個數mov ax, 0x1301 ; 子功能號13是顯示字符串及屬性, 要存入ah寄存器,; al設置顯示字符方式 ah=01: 顯示字符串,光標跟隨移動mov bx, 0x2 ; bh存儲要顯示的頁號, 此時是第0頁,; bl中是字符屬性, 屬性黑底綠字(bl = 02h)int 0x10 ; 執行BIOS 0x10 號中斷; 打印字符串結束
; -----------------------------------------------------------jmp $ ; 使程序停在此處message db "1 MBR"times 510-($-$$) db 0db 0x55,0xaa
編譯mrb.S文件:
nasm -o test mbr.s
將文件內容寫入0盤0道1扇區:
dd if=/home/abc/Desktop/Bochs/mbr.bin of=/home/abc/Desktop/Bochs/Seven.img bs=512 count=1 seek=0 conv=notrunc
啟動bochs查看結果:
bin/bochs -f bochsrc.disk
在 0x7c00
處打斷點,可以看到將0x0000
的值移入cs中:
查看段寄存器: