分析bootloader進入保護模式的過程。
在剛進入bootloader的時候,最先執行的操作分別為關閉中斷、清除eflags的df位以及將ax, ds, es, ss暫存器初始化為0;
.globl start
start:
.code16
cli //關中斷
cld //清除方向標誌
xorw %ax,
%ax //ax清0
movw %ax,
%ds //ds清0
movw %ax,
%es //es清0
movw %ax,
%ss //ss清0
為何開啟a20,以及如何開啟a20?
seta20.1:
//等待8042鍵盤控制器不忙
inb $0x64
,%al //從0x64埠中讀入乙個位元組到al中
testb $0x2
,%al //測試al的第2位
jnz seta20.
1//al的第2位為0,則跳出迴圈
movb $0xd1
,%al //將0xd1寫入al中
outb %al, $0x64
//將0xd1寫入到0x64埠中
接下來往0x64寫入0xd1命令,表示修改8042的p2 port;
movb $0xd1
,%al//將0xdf入al中
outb %al, $0x64
//將0xdf入到0x64埠中,開啟a20
接下來繼續等待input buffer為空:
seta20.2:
//等待8042鍵盤控制器不忙
inb $0x64
,%al //從0x64埠中讀入乙個位元組到al中
testb $0x2
,%al //測試al的第2位
jnz seta20.
2//al的第2位為0,則跳出迴圈
接下來往0x60埠寫入0xdf,表示將p2 port的第二個位(a20)選通置為1;
movb $0xdf
,%al //將0xdf入al中
outb %al, $0x60
//將0xdf入到0x64埠中,開啟a20
如何初始化gdt表?
原因:進入保護模式後,會啟用段機制。邏輯位址會通過段基址對映,變成線性位址,在沒有頁模式之前,線性位址就是實體地址。需要進行位址轉換,就需要段描述符。因為有很多段,就形成了乙個全域性描述符表,也就是gdt。
a) 載入gdt表
lgdt gdtdesc //載入gdt表
gdt的結構:
gdt:
seg_nullasm //空段
seg_asm
(sta_x|sta_r,
0x0,
0xffffffff
)//**段(可讀可執行)
seg_asm
(sta_w,
0x0,
0xffffffff
)//資料段(可讀可寫)
0x0:(基位址)
0xffffffff:(段大小)
大小是4g 在段設定好以後,就可以訪問4g的空間
基位址是0,就說明虛擬位址等於實體地址
gdtdesc:
.word 0x17
//段表的大小(size-1)
.long gdt //段表的位置
b) 進入保護模式:
通過將cr0暫存器pe位置1便開啟了保護模式
movl %cr0,
%eax //載入cro到eax
orl $cr0_pe_on,
%eax //將eax的第0位置為1
movl %eax,
%cr0 //將cr0的第0位置為1
上面已經開啟了保護模式,所以這裡需要用到邏輯位址。
ljmp $prot_mode_cseg, $protcseg
.code32
protcseg:
從此以後 就進入了32位位址空間了
d) 設定段暫存器,並建立堆疊
movw $prot_mode_dseg,
%ax //資料段的段描述符位址
movw %ax,
%ds
movw %ax,
%es
movw %ax,
%fs
movw %ax,
%gs
movw %ax,
%ss
使得訪問資料段的時候都能找到對應的位址空間
設定堆疊:
因為函式的呼叫和函式的變數等在堆疊所以需要設定好堆疊
movl $0x0
,%ebp //設定函式呼叫棧的開始位置
movl $start,
%esp //設定堆疊的空間大小為start esp做減操作
start從0x7c00一直壓棧 也就是往下走 所以就不會破壞空間
e) 轉到保護模式完成,進入boot主方法
call bootmain //呼叫bootmain函式
bootmain 實現載入ucore os
步驟:bootloader硬碟讀進 解析elf格式 **段 記憶體段放入記憶體位置
讀乙個扇區 bootloader位於第0個扇區 ucore os在第乙個扇區
bootmain(void) elfhdr是 對**段和資料段的記錄 包括size等 會將相應的**段和資料段讀入
作業系統實驗
一 實驗目的 理解vi的三種執行模式及其切方法。學會使用vi的各種操作命令進行文字檔案的編輯。用vi編寫linux下c程式,會用gcc編譯。二 實驗環境 一台裝有linux的機器 這裡預設是red hat linux 9 系統裡面有gcc編譯器。三 實驗內容 寫出主要的內容 首先用合法使用者登入系統...
實驗作業系統
實驗一 linux使用環境 實驗二 linux下c程式設計環境 1 設有乙個三位數,將它的百 十 個位上的3個數,各自求立方,然後加起來,正好等於這個3位數,請在linux環境下程式設計找出所有滿足條件的數,並編譯 除錯 執行你的程式。include int main return0 實驗三 程序觀...
作業系統實驗2
1 訊息的建立,傳送和接受。使用系統呼叫 msgget msgsnd msgrev 及msgctl 編制一長度為1k的訊息傳送和接受的程式。為了便於操作和觀察結果,用乙個程式做為 引子 先後fork 兩個子程序,server 和 client 程序通訊。server 端建立乙個key 為 75 的訊...