分页机制总结
【0】寫在前面(分頁(yè)機(jī)制)
- 0.0) source code from orange’s implemention of a os and text description from Zhaojiong’s perfect analysis of Linux kernel and for complete code ,please visit https://github.com/pacosonTang/Orange-s-OS/blob/master/p67.asm
- 0.1)本代碼旨在演示 怎樣開啟分頁(yè)機(jī)制 + 怎樣構(gòu)建頁(yè)目錄和頁(yè)表
- 0.3)本文 只對(duì) 與 分頁(yè)機(jī)制的 代碼進(jìn)行簡(jiǎn)要注釋,言簡(jiǎn)意賅;
- 0.4) 為了讓廣大小白(像我一樣對(duì)os分頁(yè)機(jī)制不覺明里的小白)真真切切了解分頁(yè)機(jī)制,即使這篇文章是轉(zhuǎn)載自 “0.0” 中的兩本,但我還是將本文歸為原創(chuàng)以推薦到博客首頁(yè);(版權(quán),我已在0.0中聲明了)
; ========================================== ; pmtest6.asm ; 編譯方法:nasm pmtest6.asm -o pmtest6.com ; ==========================================%include "pm.inc" ; 常量, 宏, 以及一些說(shuō)明PageDirBase equ 200000h ; 頁(yè)目錄開始地址: 2M PageTblBase equ 201000h ; 頁(yè)表開始地址: 2M+4Korg 0100hjmp LABEL_BEGIN[SECTION .gdt] ; GDT ; 段基址, 段界限, 屬性 LABEL_GDT: Descriptor 0, 0, 0 ; 空描述符 LABEL_DESC_NORMAL: Descriptor 0, 0ffffh, DA_DRW ; Normal 描述符
; 頁(yè)目錄描述符 [add]
LABEL_DESC_PAGE_DIR: Descriptor PageDirBase, 4095, DA_DRW;Page Directory; 頁(yè)表描述符 [add]
LABEL_DESC_PAGE_TBL: Descriptor PageTblBase, 1023, DA_DRW|DA_LIMIT_4K;Page TablesLABEL_DESC_CODE32: Descriptor 0, SegCode32Len-1, DA_C+DA_32 ; 非一致代碼段, 32 LABEL_DESC_CODE16: Descriptor 0, 0ffffh, DA_C ; 非一致代碼段, 16 LABEL_DESC_DATA: Descriptor 0, DataLen-1, DA_DRW ; Data LABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRWA + DA_32 ; Stack, 32 位 LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ; 顯存首地址 ; GDT 結(jié)束GdtLen equ $ - LABEL_GDT ; GDT長(zhǎng)度 GdtPtr dw GdtLen - 1 ; GDT界限dd 0 ; GDT基地址; GDT 選擇子 SelectorNormal equ LABEL_DESC_NORMAL - LABEL_GDT SelectorPageDir equ LABEL_DESC_PAGE_DIR - LABEL_GDT SelectorPageTbl equ LABEL_DESC_PAGE_TBL - LABEL_GDT SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT SelectorCode16 equ LABEL_DESC_CODE16 - LABEL_GDT SelectorData equ LABEL_DESC_DATA - LABEL_GDT SelectorStack equ LABEL_DESC_STACK - LABEL_GDT SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT ; END of [SECTION .gdt][SECTION .data1] ; 數(shù)據(jù)段 ALIGN 32 [BITS 32] LABEL_DATA: SPValueInRealMode dw 0 ; 字符串 PMMessage: db "In Protect Mode now. ^-^", 0 ; 進(jìn)入保護(hù)模式后顯示此字符串 OffsetPMMessage equ PMMessage - $$ DataLen equ $ - LABEL_DATA ; END of [SECTION .data1]; 全局堆棧段 [SECTION .gs] ALIGN 32 [BITS 32] LABEL_STACK:times 512 db 0TopOfStack equ $ - LABEL_STACK - 1; END of [SECTION .gs][SECTION .s16] [BITS 16] LABEL_BEGIN:mov ax, csmov ds, axmov es, axmov ss, axmov sp, 0100hmov [LABEL_GO_BACK_TO_REAL+3], axmov [SPValueInRealMode], sp; 初始化 16 位代碼段描述符mov ax, csmovzx eax, axshl eax, 4add eax, LABEL_SEG_CODE16mov word [LABEL_DESC_CODE16 + 2], axshr eax, 16mov byte [LABEL_DESC_CODE16 + 4], almov byte [LABEL_DESC_CODE16 + 7], ah; 初始化 32 位代碼段描述符xor eax, eaxmov ax, csshl eax, 4add eax, LABEL_SEG_CODE32mov word [LABEL_DESC_CODE32 + 2], axshr eax, 16mov byte [LABEL_DESC_CODE32 + 4], almov byte [LABEL_DESC_CODE32 + 7], ah; 初始化數(shù)據(jù)段描述符xor eax, eaxmov ax, dsshl eax, 4add eax, LABEL_DATAmov word [LABEL_DESC_DATA + 2], axshr eax, 16mov byte [LABEL_DESC_DATA + 4], almov byte [LABEL_DESC_DATA + 7], ah; 初始化堆棧段描述符xor eax, eaxmov ax, dsshl eax, 4add eax, LABEL_STACKmov word [LABEL_DESC_STACK + 2], axshr eax, 16mov byte [LABEL_DESC_STACK + 4], almov byte [LABEL_DESC_STACK + 7], ah; 為加載 GDTR 作準(zhǔn)備xor eax, eaxmov ax, dsshl eax, 4add eax, LABEL_GDT ; eax <- gdt 基地址mov dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址; 加載 GDTRlgdt [GdtPtr]; 關(guān)中斷cli; 打開地址線A20in al, 92hor al, 00000010bout 92h, al; 準(zhǔn)備切換到保護(hù)模式mov eax, cr0or eax, 1mov cr0, eax; 真正進(jìn)入保護(hù)模式j(luò)mp dword SelectorCode32:0 ; 執(zhí)行這一句會(huì)把 SelectorCode32 裝入 cs, 并跳轉(zhuǎn)到 Code32Selector:0 處;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;LABEL_REAL_ENTRY: ; 從保護(hù)模式跳回到實(shí)模式就到了這里mov ax, csmov ds, axmov es, axmov ss, axmov sp, [SPValueInRealMode]in al, 92h ; ┓and al, 11111101b ; ┣ 關(guān)閉 A20 地址線out 92h, al ; ┛sti ; 開中斷mov ax, 4c00h ; ┓int 21h ; ┛回到 DOS ; END of [SECTION .s16][SECTION .s32]; 32 位代碼段. 由實(shí)模式跳入. [BITS 32]LABEL_SEG_CODE32:; 開啟分頁(yè)機(jī)制的初始化工作,該指令執(zhí)行后,cpu即可開啟分頁(yè)機(jī)制[add]
call SetupPagingmov ax, SelectorDatamov ds, ax ; 數(shù)據(jù)段選擇子mov ax, SelectorVideomov gs, ax ; 視頻段選擇子mov ax, SelectorStackmov ss, ax ; 堆棧段選擇子mov esp, TopOfStack; 下面顯示一個(gè)字符串mov ah, 0Ch ; 0000: 黑底 1100: 紅字xor esi, esixor edi, edimov esi, OffsetPMMessage ; 源數(shù)據(jù)偏移mov edi, (80 * 10 + 0) * 2 ; 目的數(shù)據(jù)偏移。屏幕第 10 行, 第 0 列。cld .1:lodsbtest al, aljz .2mov [gs:edi], axadd edi, 2jmp .1 .2: ; 顯示完畢; 到此停止jmp SelectorCode16:0; [add]啟動(dòng)分頁(yè)機(jī)制 ————————————————————–
SetupPaging:; 為簡(jiǎn)化處理, 所有線性地址對(duì)應(yīng)相等的物理地址.
; 首先初始化頁(yè)目錄
; 這里是在初始化頁(yè)目錄中項(xiàng)的內(nèi)容,即對(duì)應(yīng)頁(yè)表的內(nèi)存地址
.1: stosd;stosb, stosw, stosd 把a(bǔ)l/ ax/ eax的內(nèi)容存儲(chǔ)到 es:edi 指向的內(nèi)存單元中, 該指令執(zhí)行后,edi自增1
add eax, 4096; 為了簡(jiǎn)化, 所有頁(yè)表在內(nèi)存中是連續(xù)的.,每個(gè)頁(yè)表占用4k字節(jié)空間
loop .1; 初始化頁(yè)目錄的項(xiàng)內(nèi)容 over
; 再初始化所有頁(yè)表 (1K 個(gè), 4M 內(nèi)存空間)的項(xiàng)內(nèi)容,即頁(yè)表的項(xiàng)存儲(chǔ)的是內(nèi)存地址的高20位地址;
; 初始化頁(yè)表的項(xiàng)內(nèi)容 over
mov eax, PageDirBase; 加載頁(yè)目錄的基地址到 cr3
mov cr3, eax; 設(shè)置cr0的PG位=1,開啟分頁(yè)機(jī)制
mov eax, cr0or eax, 80000000hmov cr0, eaxjmp short .3 .3:nopret; 分頁(yè)機(jī)制啟動(dòng)完畢 ———————————————————-
SegCode32Len equ $ - LABEL_SEG_CODE32 ; END of [SECTION .s32]; 16 位代碼段. 由 32 位代碼段跳入, 跳出后到實(shí)模式 [SECTION .s16code] ALIGN 32 [BITS 16] LABEL_SEG_CODE16:; 跳回實(shí)模式:mov ax, SelectorNormalmov ds, axmov es, axmov fs, axmov gs, axmov ss, axmov eax, cr0and eax, 7FFFFFFEh ; PE=0, PG=0mov cr0, eaxLABEL_GO_BACK_TO_REAL:jmp 0:LABEL_REAL_ENTRY ; 段地址會(huì)在程序開始處被設(shè)置成正確的值Code16Len equ $ - LABEL_SEG_CODE16; END of [SECTION .s16code]3.3 頁(yè)式存儲(chǔ)總結(jié)
分段機(jī)制將邏輯地址轉(zhuǎn)換成線性地址,線性地址通過(guò)分頁(yè)機(jī)制轉(zhuǎn)換成物理地址。
為什么使用分頁(yè)?(干貨)
分頁(yè)管理機(jī)制的目的在于實(shí)現(xiàn)虛擬存儲(chǔ)器,線性地址中的任意一個(gè)頁(yè)都能映射到物理地址中的任何一個(gè)頁(yè),使得內(nèi)存管理機(jī)制特別靈活。
分頁(yè)和分段的最大不同之處在于?(干貨)
- 1)段的長(zhǎng)度不固定: 段的長(zhǎng)度通常與存放在其中的代碼和數(shù)據(jù)結(jié)構(gòu)具有相同的長(zhǎng)度;
- 2)頁(yè)面長(zhǎng)度固定:頁(yè)面具有固定的長(zhǎng)度;
- 3)如果僅使用分段地址轉(zhuǎn)換:那么存儲(chǔ)在物理內(nèi)存中的一個(gè)數(shù)據(jù)結(jié)構(gòu)將包含所有的部分;
- 4)如果使用了分頁(yè),那么一個(gè)數(shù)據(jù)結(jié)構(gòu)就可以一部分存儲(chǔ)在物理內(nèi)存中,一部分存儲(chǔ)在磁盤上(虛擬存儲(chǔ)器);
- 5)為了減少地址轉(zhuǎn)換所要求的總線總起數(shù)量,最近訪問(wèn)的頁(yè)目錄和頁(yè)表會(huì)被存放在處理器的緩沖器件中,該緩沖器件被稱為TLB(translation lookaside buffer,翻譯后備緩沖寄存器),提高訪存效率;
3.3.1 分頁(yè)機(jī)制概述
Why-為什么使用兩極頁(yè)表結(jié)構(gòu)?
- w1)頁(yè)表含有2^20(1M)個(gè)表項(xiàng),每項(xiàng)占4字節(jié)。如果用一個(gè)表來(lái)存儲(chǔ)的話,將最多占用4M;為減少內(nèi)存占用量,X86使用了兩極頁(yè)表;
w2)每個(gè),僅有一個(gè)頁(yè)目錄占用4k, 每個(gè)頁(yè)表占用4k,而要知道頁(yè)目錄一定常駐內(nèi)存,而頁(yè)表是在需要的時(shí)候才占用內(nèi)容空間,當(dāng)然常用的頁(yè)表會(huì)存儲(chǔ)在TLB中,這在一定程度上減少了
頁(yè)表機(jī)制進(jìn)行線性地址與物理地址映射所占用內(nèi)存空間;(干貨)1)第一級(jí)頁(yè)表——頁(yè)目錄(bit31~22):頁(yè)目錄項(xiàng)存儲(chǔ)的內(nèi)容是頁(yè)表的基地址(高20位存儲(chǔ)頁(yè)表基地址,低12位存儲(chǔ)所指向的頁(yè)表屬性)(干貨); 它被存放在1頁(yè)4k頁(yè)面中, 含有1k個(gè)4字節(jié)長(zhǎng)度的表項(xiàng),通過(guò)線性地址的bit31~22進(jìn)行索引頁(yè)目錄表項(xiàng);
2)第二級(jí)頁(yè)表——頁(yè)表(bit21~12):頁(yè)表項(xiàng)存儲(chǔ)的內(nèi)容是物理頁(yè)的基地址(高20位存儲(chǔ)物理頁(yè)基地址,低12位存儲(chǔ)物理頁(yè)屬性)(干貨); 它被存放在1頁(yè)4k頁(yè)面中,含有1k個(gè)4字節(jié)長(zhǎng)度的表項(xiàng),而該頁(yè)表的表項(xiàng)由 bit21~12進(jìn)行定位;
3)偏移地址(bit11~0):它存儲(chǔ)的是物理頁(yè)的第12位地址(干貨); 把頁(yè)表項(xiàng)存儲(chǔ)的高20位地址作為物理頁(yè)的高20位地址,而偏移地址12位作為物理頁(yè)的低12位地址,這樣就得到了32位的物理地址;
- 4)映射到的物理地址空間:頁(yè)長(zhǎng)4k,總共有1k個(gè)頁(yè)目錄項(xiàng),每個(gè)頁(yè)目錄項(xiàng)映射一張頁(yè)表,每張頁(yè)表有1k個(gè)頁(yè)表項(xiàng);故總共1k * 1k =1M個(gè)頁(yè)表項(xiàng);所以物理地址空間=1M * 4k = 4G
(you should know):
Y1)頁(yè)目錄的基地址存儲(chǔ)在cr3中;
Y2)開啟分頁(yè)機(jī)制,要設(shè)置cr0的最高位PG位=1;
總結(jié)
- 上一篇: 万网空间怎么续费(万网空间怎么续费会员)
- 下一篇: 如何从文件系统中读取文件内容