學(xué)習(xí)筆記
《x86匯編語(yǔ)言:從實(shí)模式到保護(hù)模式》
http://www.reibang.com/p/d481cb547e9f
方案的內(nèi)容
每個(gè)任務(wù)都有自己的頁(yè)目錄表以及頁(yè)表诗越,
頁(yè)目錄表的前半部分對(duì)應(yīng)著任務(wù)自己虛擬地址空間的前2GB(0~2G)
后半部分則映射到內(nèi)核的頁(yè)表(2~4G);
- 當(dāng)任務(wù)在自己獨(dú)立的局部空間工作時(shí),使用它自己的頁(yè)表油讯;
- 當(dāng)任務(wù)請(qǐng)求系統(tǒng)服務(wù)時(shí),用的則是內(nèi)核的頁(yè)表颗品,訪問(wèn)的是內(nèi)核的代碼和數(shù)據(jù)趾徽;
本文只涉及頁(yè)目錄表相關(guān)。
-
[1]惨远、創(chuàng)建用戶任務(wù)的頁(yè)目錄表(
頁(yè)目錄表(user)
); -
[2]谜悟、將內(nèi)核頁(yè)目錄表(
頁(yè)目錄表(core)
)中的內(nèi)容復(fù)制過(guò)去话肖; - [3]、切換到用戶任務(wù)的頁(yè)目錄表上去工作葡幸;
代碼過(guò)程
- 源碼文件
c16_core.asm
- 前面的數(shù)字代表語(yǔ)句在源碼文件中的行號(hào)最筒;
零、調(diào)用 過(guò)程 load_relocate_program
1067 call load_relocate_program
一蔚叨、過(guò)程 load_relocate_program 的內(nèi)部調(diào)用
830 ;創(chuàng)建用戶任務(wù)的頁(yè)目錄
831 ;注意床蜘!頁(yè)的分配和使用是由頁(yè)位圖決定的,可以不占用線性地址空間
; 調(diào)用過(guò)程 create_copy_cur_pdir
832 call sys_routine_seg_sel:create_copy_cur_pdir
833 mov ebx,[es:esi+0x14] ;從TCB中獲取TSS的線性地址
834 mov dword [es:ebx+28],eax ;填寫TSS的CR3(PDBR)域
- 調(diào)用過(guò)程
create_copy_cur_pdir
蔑水,完成方案中的[1]以及[2]邢锯; - 在過(guò)程
create_copy_cur_pdir
返回之后,更新了用戶任務(wù)的TSS的CR3域搀别,從而完成了方案中的[3]
二丹擎、過(guò)程 create_copy_cur_pdir 的具體實(shí)現(xiàn)
create_copy_cur_pdir: ;創(chuàng)建新頁(yè)目錄,并復(fù)制當(dāng)前頁(yè)目錄內(nèi)容
;輸入:無(wú)
;輸出:EAX=新頁(yè)目錄的物理地址
push ds
push es
push esi
push edi
push ebx
push ecx
mov ebx,mem_0_4_gb_seg_sel
mov ds,ebx
mov es,ebx
call allocate_a_4k_page
mov ebx,eax
or ebx,0x00000007
mov [0xfffffff8],ebx
mov esi,0xfffff000 ;ESI->當(dāng)前頁(yè)目錄的線性地址
mov edi,0xffffe000 ;EDI->新頁(yè)目錄的線性地址
mov ecx,1024 ;ECX=要復(fù)制的目錄項(xiàng)數(shù)
cld
repe movsd
pop ecx
pop ebx
pop edi
pop esi
pop es
pop ds
retf
1歇父、通過(guò)call allocate_a_4k_page
為用戶任務(wù)申請(qǐng)了一個(gè)新的空閑的物理頁(yè)蒂培,作為用戶任務(wù)的頁(yè)目錄表,記為頁(yè)目錄表(user)
榜苫,即書上所稱的新頁(yè)目錄表护戳;
2、給頁(yè)目錄表(user)
的物理地址填上頁(yè)的屬性:US=1(只有特權(quán)級(jí)為3的用戶程序可以訪問(wèn)該頁(yè))单刁、RW=1(頁(yè)是可讀可寫的)灸异、P=1(頁(yè)位于物理內(nèi)存中)
mov ebx,eax
or ebx,0x00000007
3、裝填好頁(yè)屬性的頁(yè)目錄表(user)
的物理地址怎么處理羔飞?放到頁(yè)目錄表(core)
的倒數(shù)第二個(gè)表項(xiàng)里去肺樟,頁(yè)目錄表(core)
,就是內(nèi)核程序的頁(yè)目錄表逻淌,即書上所稱的當(dāng)前頁(yè)目錄表(看完步驟4么伯,一起看圖解)
mov [0xfffffff8],ebx
4、為什么頁(yè)目錄表(user)
的線性地址是0x FFFF E000
?
回顧 為什么
頁(yè)目錄表(core)
的線性地址是0x FFFF F000
http://www.reibang.com/p/d6b534560669
- 為什么`頁(yè)目錄表(user)`的線性地址是`0x FFFF E000`.png
首先卡儒,由于步驟3田柔,
頁(yè)目錄(core)
的倒數(shù)第二個(gè)表項(xiàng),填入了剛分配的物理頁(yè)的物理地址骨望,而這個(gè)物理頁(yè)正是分配給用戶程序做頁(yè)目錄表用的硬爆;現(xiàn)在是在內(nèi)核程序里面,調(diào)用的過(guò)程擎鸠,因此CR3寄存器的內(nèi)容指向的正是內(nèi)核程序的頁(yè)目錄表缀磕;
頁(yè)目錄表(core)
的倒數(shù)第一項(xiàng)在很早的時(shí)候就已經(jīng)被填好了自己的物理地址;
具體的時(shí)間點(diǎn)在源碼文件`c16_core.asm`是這樣的:
開啟分頁(yè)機(jī)制之后
(第969~973行) 在倒數(shù)第一項(xiàng)填入自己的物理地址
具體實(shí)現(xiàn)與圖解
可見 http://www.reibang.com/p/c251257329fe
....
....
....
(1067行) call load_relocate_program
回到本文上方看標(biāo)題,就可以明白邏輯順序
call load_relocate_program
|---- call sys_routine_seg_sel:create_copy_cur_pdir
- 由倒數(shù)第二個(gè)表項(xiàng)的偏移量應(yīng)該是
0xFF8
就可以逆推出中10位是0x3FE
袜蚕,全部寫成二進(jìn)制的序列就是0011 1111 1110
糟把,而根據(jù)線性地址的格式,也可以知道最開始的兩個(gè)零牲剃,其實(shí)是自己的補(bǔ)零遣疯,那么中10位本質(zhì)上就是11 1111 1110
,全部組合起來(lái)凿傅,就可以得到頁(yè)目錄表(user)
的線性地址是0x FFFF E000
缠犀; - 因此,驗(yàn)證了書上的結(jié)論:
`頁(yè)目錄表(user)`的線性地址是`0x FFFF E000`
`頁(yè)目錄表(core)`的線性地址是`0x FFFF F000`
5聪舒、將內(nèi)核頁(yè)目錄表中的內(nèi)容復(fù)制過(guò)去
mov esi,0xfffff000 ;ESI->當(dāng)前頁(yè)目錄的線性地址
mov edi,0xffffe000 ;EDI->新頁(yè)目錄的線性地址
mov ecx,1024 ;ECX=要復(fù)制的目錄項(xiàng)數(shù)
cld
repe movsd
- 復(fù)制操作的匯編指令rep的語(yǔ)法就是這樣的夭坪, 只要提供源地址、目的地址并且指定傳送方向即可过椎;
rep 相關(guān)具體語(yǔ)法參見 http://www.reibang.com/p/1b17ad3ad51f
- 值得一提的是,因?yàn)楝F(xiàn)在的內(nèi)核程序運(yùn)行已經(jīng)開啟了分頁(yè)機(jī)制戏仓,所以源地址和目的地址都要提供線性地址疚宇,我們需要把目錄表(core)的內(nèi)容全部復(fù)制給目錄表(user),就需要知道兩個(gè)東西的線性地址赏殃。