读书人

(第三章 14)精打细算用内存初始

发布时间: 2012-07-02 17:46:23 作者: rapoo

(第三章 14)克勤克俭用内存——初始化页目录表、页表,开启分页机制

在启动分页机制SetupPaging之前,先调用了DispMemSize函数,在函数中计算出了[dwMemSize]——最大内存地址值。

?

; 启动分页机制 --------------------------

SetupPaging:

;1、计算出最大地址为[dwMemSize]对应的内存共有多少个页表(也即PDE个数,不是页面个数),将个数(ecx,32bit)压栈

xoredx, edx

moveax, [dwMemSize]

movebx, 400000h; 400000h = 4M = 4096 * 1024, 一个页表对应的内存大小(一个页面是4k,一个页表有1024个页面)

divebx ? ? ? ? ? ? ; edx:eax / ebx ==> eax ...... edx

movecx, eax; 此时 ecx 为页表的个数,也即 PDE 应该的个数

testedx, edx

jz.no_remainder

incecx; 如果余数不为 0 就需增加一个页表

.no_remainder:

pushecx; 暂存页表个数

?

; 为简化处理, 所有线性地址对应相等的物理地址. 并且不考虑内存空洞.

?

;2、首先初始化“页目录表”(即初始化每个PDE)

movax, SelectorPageDir; 此段首地址为 PageDirBase

moves, ax

xoredi, edi

xoreax, eax

moveax, PageTblBase | PG_P ?| PG_USU | PG_RWW

.1:

stosd ? ? ? ? ? ? ? ? ? ? ? ? ? ; eax中的4个字节 -> es:edi ,每循环一次是一个PDE

addeax, 4096; 为了简化, 所有页表在内存中是连续的.

loop.1 ? ? ? ? ? ? ? ? ? ? ?; 循环次数为ecx=PDE个数

?

;3、再初始化所有“页表”,即初始化每个PTE

movax, SelectorPageTbl; 此段首地址为 PageTblBase

moves, ax

popeax; 页表个数,也是PDE个数

movebx, 1024; 每个页表 1024 个 PTE

mulebx ? ? ? ? ? ? ? ? ? ? ; eax*ebx==>积edx:eax

movecx, eax; PTE个数 = 页表个数 * 1024

xoredi, edi

xoreax, eax

moveax, PG_P ?| PG_USU | PG_RWW

.2:

stosd ? ? ? ? ? ? ? ? ? ? ? ? ? ; eax==>es:edi

addeax, 4096; 每一页指向 4K 的空间

loop.2 ? ? ? ? ? ? ? ? ? ? ?; 循环次数为ecx=PTE个数

?

;4、开启页表机制

moveax, PageDirBase

movcr3, eax

?

moveax, cr0

oreax, 80000000h

movcr0, eax

?

jmpshort .3

.3:

nop

?

ret

; 分页机制启动完毕 ----------------------

读书人网 >操作系统

热点推荐