分类:
2010-09-04 00:02:58
关于书中:
一个表项4B
一个页目录4KB=4B *1024 个表项
一个页表 4KB =4B * 1024个表项
页目录的一个表项对应一个页表
一个页的表项对应一个物理页大小4KB
一个页表对应的内存大小4KB *1024 =4MB
8个页表 即 4KB * 8 =32KB 段界限 32KB -1
分页机制的启动
PageDirBase equ 200000h ; 页目录开始地址:
PageTblBase equ 201000h ; 页表开始地址:
LABEL_DESC_PAGE_DIR: Descriptor PageDirBase, 4095, DA_DRW ; Page Directory
LABEL_DESC_PAGE_TBL: Descriptor PageTblBase, 4096 * 8 - 1, DA_DRW ; Page Tables
SelectorPageDir equ LABEL_DESC_PAGE_DIR - LABEL_GDT
SelectorPageTbl equ LABEL_DESC_PAGE_TBL - LABEL_GDT
; 启动分页机制 --------------------------------------------------------------
SetupPaging:
; 根据内存大小计算应初始化多少PDE以及多少页表
xor edx, edx
mov eax, [dwMemSize]
mov ebx, 400000h ; 400000h =
div ebx
mov ecx, eax ; 此时 ecx 为页表的个数,也即 PDE 应该的个数
test edx, edx
jz .no_remainder
inc ecx ; 如果余数不为 0 就需增加一个页表
.no_remainder:
push ecx ; 暂存页表个数
; 为简化处理, 所有线性地址对应相等的物理地址. 并且不考虑内存空洞.
; 首先初始化页目录
mov ax, SelectorPageDir ; 此段首地址为 PageDirBase
mov es, ax
xor edi, edi
xor eax, eax
mov eax, PageTblBase | PG_P | PG_USU | PG_RWW
.1:
stosd
add eax, 4096 ; 为了简化, 所有页表在内存中是连续的.
loop .1
; 再初始化所有页表
mov ax, SelectorPageTbl ; 此段首地址为 PageTblBase
mov es, ax
pop eax ; 页表个数
mov ebx, 1024 ; 每个页表 1024 个 PTE
mul ebx
mov ecx, eax ; PTE个数 = 页表个数 * 1024
xor edi, edi
xor eax, eax
mov eax, PG_P | PG_USU | PG_RWW
.2:
stosd
add eax, 4096 ; 每一页指向 4K 的空间
loop .2
mov eax, PageDirBase
mov cr3, eax
mov eax, cr0
or eax, 80000000h
mov cr0, eax
jmp short .3
.3:
nop
ret
; 分页机制启动完毕 ----------------------------------------------------------
dwMemSize equ _dwMemSize - $$
_dwMemSize: dd 0
在实模式下使用_dwMemSize,在保护模式下使用dwMemSize。因为程序是在保护模式下编译的,地址只适用于实模式,在保护模式下数据的地址是相对于其段的偏移。虽然前面有过自己却没有注意,哎。。。。。
还有一个问题是没有得到显示的
chinaunix网友2011-01-07 18:26:03
很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com