Chinaunix首页 | 论坛 | 博客
  • 博客访问: 488815
  • 博文数量: 164
  • 博客积分: 4024
  • 博客等级: 上校
  • 技术积分: 1580
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-10 16:27
文章分类

全部博文(164)

文章存档

2011年(1)

2010年(108)

2009年(55)

我的朋友

分类:

2010-06-28 13:47:17

[386分页机制]

 

一、

页也就是指内存中的一块区域,在80386中页的大小是4KB,这个是可以计算出来的(线性地址的低12位0FFFh 是页的最大偏移。所以4KB是也页的最大界限)。

在Pentuim 系列后页的大小可以是2MB或者4MB,并且可以用页访问多于4GB的空间。

 

1、在未开启分页机制之前的寻址方式

根据保护模式的分段机制,[段选择子:EA] =》(检查) =》 线性地址 =》物理地址。

如上可以直接通过分段机制获得物理地址。

 

2、在开启分页机制后的寻址方式:

开启分页机制需要将cr0的PG位置1.。支持分页机制的是cr3指向的一个页目录表。

它的结构是这样的:

 

        PDEs(Page Directory Entry)

     _________________________||______________________________

     |                            |                             |                           |                          |   

     D1                      D2                          D3                     .....                  D1024

____||____        ____||____                ____||____                                ____||____

   PTE1s                PTE2s                      PTE3s                                      PTE4s   

   |          |               |        |                       |             |                                 |            |

T1_1 ... T1_1024   T2_1 ... T2_1024    T3_1 ... T3_1024            T4_1 ... T4_1024

 

来说说这个结构图:

1、 PDEs(Page Directory Entry)

页目录表总大小是4KB,因为它有1024个页目录项,并且每个页目录项的大小是4个字节。

它的每一个页目录项分别指向一个页表。

2、 PTEs(Page Table Entry)

页表含有1024个表项,其中每个表项对应一个物理页面。

最主要还是要得到表的信息,因为其他的都是表的目录。PDEs是根目录。D1-D1024是根目录下的子目录。D1-D1024各对应着表PTE1s-PTE1024s。PTE1s-PTE1024s每个目录都存放着1024个表项。在表项里面才可以得到真正需要的物理基地址。 要得到表项里的数据必需:

得到D(n)---->>得到PTE(n)s----->>得到T(m)---->得到物理基址。

那么在转换成线性地址后:

1、CPU先取出线性地址的22-31位,高10位相当于一个页目录项的索引。用这个索引在cr3指定的页目录表找到该目录项,页目录项对应一个页表。即得到该线性地址的页表位置。

2、然后取出线性地址的12-21位,中间的10位相当于一个表项索引。

即可以得到线性地址的表项。 而表项里面正存着物理基地址呢。

3、 最后取出0-11位,低12位也就是偏移(EA)。可以认为是物理段偏移。

那么用得到 物理页首地址 + 偏移 = 正确的物理地址。

 

 

二、 分页机制

 

在打开分页机制后, CPU会将最近常用到的页目录和页表项保存在TLB(Translation Lookaside Buffe)

 

 

中,只有在TLB中找不到被请求的页的转换信息时,才会去内存中寻找。

 

 

 

当页目录或页表项被更改时,操作系统应该马上使TLB中对应的条目失效。以便下次用到此条目时能从内存

 

 

中获取更新的信息。

 

 

当cr3被加载时,所有的TLB都会自动无效,除非页或者页表条目的G位被设置.

 

 

cr3寄存器指向页目录表,它的高20位就是页目录表首地址的高20位,cr3的低12位会是零,因为页目录表基

 

 

址是以4KB对齐的。

 

 

 

说了这么多目目录、页表,那么到底页目录与页表是一个怎么样的关系呢?下面就来详细的介绍他们之间的

 

 

关系:

 

 

 

页目录表简称:PDEs,页表简称:PTEs.

 

 

 

cr3中的高20位*4KB也就是目录表(PDEs)的基址了,得到页目录表基址后。所有的页目录就都出来了

 

 

PDEs页目录表,它包含了1024个PDE目录项,其中每个目录项对应一个PTEs.(页表)

 

 

先看看第一个页目录项PDE,它的12-31位值* 4KB指向的是第一个PTEs(页表)的位置。

 

 

第一个PTEs里面也包含1024个页表项,第一个PTE(页表项)的12-31位值*4KB指向的就是页基地址的位置.这

 

 

个时候的值就是物理基址。

如果想线性地址是0.,而物理地址是其他的.。那么可以把第0页目录项指向的页表中的第0个页表项的12 -31

位数据改成非0的物理基地址就可以了。。。

 

而PDE与PTE的关系是:

PEDs下的每一个PDE的12-31位*4KB分别指向对应一个PTEs的物理基地址.

而PTEs里的的每一个表项的12-31位的值就是当前表项对应的物理页基地址。并且界限是0ffffh。

 

三、 根据BIOS检查内存

为了节约内存,所以首先可以先检查PC机器的内存大小,。这样就知道用不用映射4GB的空间了

因为需要调用15hBIOS中断,所以为了方便直接在8086实模式入口处直接使用。

 

Int 15h 需要输入的数据:

mov          eax,0e820h     ;功能号

mov           ebx,0 ;第一个后续值是0 。这个BIOS会自动填补下一个地址描述符的后续值。

mov          ecx,20;BIOS通常规定只填充20个BYTE,所以固定20

mov          edx,0534D4150h ;BIOS将会使用这个标志,对调用者将要请求的系统映像信息进行校验,校验成功后会被放置到es:di 指向的内存缓冲区中。也就是20BYTE的地址描述符.

接下来就可以 int 15h 了。调用中断后。BIOS会根据寄存器对应的信息反馈一些信息到对应的地方。

这里就列举获取内存信息需要的:

CF;如果CF等于1表示获取错误

eax; 存放着SMAP,也就是输入的edx.验证成功返回到eax

es:di;指向的如果获取成功了,那么es:di里面就会指向n个地址范围描述符信息的基址。其中一个地址范围描述符是20个BYTE。

ecx;被BIOS填充到地址范围描述符中的字节数量。最少是20

ebx,后续值 第一次是0,NEXT后BIOS会自动填充。

得到es:di指向的所以地址描述符结构体后,就可以使用dwBaseAddrLow+dwLengthLow得到内存上限的大小。也就是可以使用的内存最大值

四、具体分页设计:

分页学起来确实有点复杂,,因为牵涉的东西太多。

段内寻址、段外寻址、特权级、等等以前的知识点都要用到。

就来说说怎样编程实现分页吧:

1、需要先给页目录项附初始值。这个值分别对应着页表的物理基地址。

2、给页目录对应的页表附物理页基址,这个值是物理地址,可以从0开始.也可以不从0开始.在线性转换中会根据低12位偏移来换算。fffh能代表的也是4KB所以一个表项目最多能表示4KB的物理页,而一个表是1024个表项,那么可以表示4MB的内存页空间.

3、将页目录表的基地址装入cr3 并打开CR0的PG位。这样就启动了分页了.

 

五、总结:

1、访问数据时要注意数据所属于的段。

2、访问代码时要注意CPL对方DPL RPL。

3、在调用返回时要注意是RET 还是RETF

注意堆栈的指向。等

阅读(834) | 评论(0) | 转发(0) |
0

上一篇:保护模式编程四

下一篇:保护模式编程六

给主人留下些什么吧!~~