开启分页机制
1. 分页的作用
在我们进行程序开发的时候,一般情况下,是不需要管理内存的,也不需要操心内存够不够用,其实,这就是分页机制给我们带来的好处。它是实现虚拟存储的关键,位于线性地址与物理地址之间,在使用这种内存分页管理方法时,每个执行中的进程(任务)可以使用比实际内存容量大得多的连续地址空间。而且当系统内存实际上被分成很多凌乱的块时,它可以建立一个大而连续的内存空间的映象,好让程序不用操心和管理这些分散的内存块。分页机制增强了分段机制的性能。页地址变换是建立在段变换基础之上的。因为,段管理机制对于Intel处理器来说是最基本的,任何时候都无法关闭。所以即使启用了页管理功能,分段机制依然是起作用的,段部件也依然工作。
2.两级页表结构
①内存分页管理的基本原理是将整个主内存区域划分成 4096 字节为一页的内存页面。程序申请使用内存时,就以内存页为单位进行分配。
②线性地址经过分页机制的转换变成物理地址,其实是通过两个表,一个是页目录表PDE,也叫一级目录,另一个是二级页表PTE。进程的虚拟地址需要首先通过其局部段描述符变换为 CPU 整个线性地址空间中的地址, 然后再使用页目录表 PDE(一级页表)和页表 PTE(二级页表)映射到实际物理地址页上。
③页表中,每项的大小是32b,其中20b用来存放页面的物理地址,12b用于存放属性信息。页表含有1M个表项,每项4B。第一级表是页目录,存放在1页4k页面中,含有1K个表项。第二级是页表,也是1K个表项。
也就是说每个页目录项中 指向一个页表,1个页表中有1K个页表项,每个页表项中存储着物理地址
④那么32位地址就被划分成了三部分
前10位是在一级目录中的索引,之后的10位是在二级目录中的索引,最后的低12位 那就是偏移地址了
低12位 代表了在一个4K页中的偏移
3.地址转换过程
①用虚拟地址的高10位4,作为页目录项表内的偏移地址,加上页目录表的物理地址,便是页目录项的物理地址,读取该地址的内容,从而获取到页表的物理地址
②用虚拟地址的中间10位4,作为页表内的偏移地址,加上在第一步得到的页表的物理地址,便是该页表项的物理地址,从而得到分配的物理地址
③得到分配的物理地址后,加上最后12位的页内偏移量,得到最终的物理地址
4. 开启分页
1.准备好页目录表和页表
2.将页表地址写入控制寄存器CR0
3.寄存器CR0的PG位置1
5.代码
这里需要注意的是,我们的操作系统是占据在虚拟内存的3GB-4GB的位置
操作系统占据了1GB的空间,一个页目录项 = 10244k = 4M,那么操作系统需要占据1GB/4M = 256个目录项,那么他占据的是高地址,就是从(1024-256) = 768个目录项开始,每个目录项占据4B,也就是7684 = 0xC00的由来
;/*******Page Table attitube**********/
PG_P EQU 1b
PG_RW_R EQU 00b
PG_RW_W EQU 10b
PG_US_S EQU 000b
PG_US_U EQU 100b
.SetUp_Page:
我们的页表项总共占4K
;/*******Clear PDE**********/
MOV ECX, 4096 ;1024*4B PDE size
MOV ESI, 0
MOV EBX, PAGE_DIR_TABLE_ADD
.Clear_PDE:
MOV byte [EBX+ESI*4], 0 ;逐位清除页表项
INC ESI
LOOP .Clear_PDE
;/*******Create PDE***********/
.Create_PDE:
MOV EAX, PAGE_DIR_TABLE_ADD 页表的地址直接放在页表项之上
ADD EAX, 0x1000 ;第一个页表 0x1000 = 4k 0x101000
MOV EBX, EAX
OR EAX, PG_US_U | PG_RW_W | PG_P 设置属性
MOV [PAGE_DIR_TABLE_ADD + 0], EAX
;将第一个页目录项和第768个目录项都指向第一个页表
MOV [PAGE_DIR_TABLE_ADD + 0xC00], EAX; 0xC00/4B = 768
;(1024-768)*4M = 1G
SUB EAX, 0x1000 最后一个目录项 指向他自己
MOV [PAGE_DIR_TABLE_ADD+4092], EAX; 1023*4
我们的内核很小,是放置在低端物理地址的1M内的
;/**********Create PTE*********/
MOV ECX, 256 ;256*4K = 1M
MOV ESI, 0
MOV EDX, PG_US_U | PG_RW_W | PG_P
.Create_PTE:
MOV [EBX+ESI*4], EDX
ADD EDX, 4096 ;4K
INC ESI
LOOP .Create_PTE
创建内核其他页表的PDE
;/*******Create other PDE********/
MOV EAX, PAGE_DIR_TABLE_ADD
ADD EAX, 0x2000 ;second page table
OR EAX, PG_US_U | PG_RW_W | PG_P
MOV EBX, PAGE_DIR_TABLE_ADD
MOV ECX, 254
MOV ESI, 769 ;769-1022的所有目录项
.Create_Kernel_PDE:
MOV [EBX+ESI*4], EAX
INC ESI
ADD EAX, 0x1000
LOOP .Create_Kernel_PDE
RET
SGDT [GDT_PTR]
;/*****Video Map****/
我们对显存的操控 也放在了内核之中
MOV EBX, [GDT_PTR+2]
OR dword [EBX+0x18+4], 0xC0000000
ADD dword [GDT_PTR+2], 0xC0000000
ADD ESP, 0xC0000000
MOV EAX, PAGE_DIR_TABLE_ADD
MOV CR3, EAX
MOV EAX, CR0
OR EAX, 0x80000000
MOV CR0, EAX
LGDT [GDT_PTR]