a) 根据指令的性质确定应该使用那一个段寄存器,例如转移指令中的地址在代码段,而取数指令中的地址在数据段。
b) 根据寄存器的内容,以GDTR(LDTR)作为基地址,以DS(ES,CS,SS)作为偏移量,找到相应的“地址段描述结构”,方式为GDTR+DS(CS、ES..)或LDTR+DS(CS、ES…)。(注:地址段描述结构见下面)
c) 从地址段描述结构中得到基地址。
d) 将指令中发出的地址作为位移,与段描述结构中规定的段长度相比,看是否越界。
e) 根据指令的性质和段描述符中的访问权限来确定是否越权
f) 将指令中发出的地址作为位移,与基地址相加而的出实际的“物理地址”
图1
地址段描述结构:
typedef struct
{
unsigned int base24_31 : 8 //基地址的高8位
unsigned int g :1 //表示段长度单位,0表示字节,1表示4K
unsigned int d_b :1
unsigned int unused :1
unsigned int avl :1
unsigned int seg_limit_16_19:4 //段长度高4位
unsigned int p :1
unsigned int dpl :1
unsigned int s :1
unsigned int type :4
unsigned int base_0_23 :24 //基地址的低24位
unsigned int seg_limit_0_15:16 //段长度的低16位
}
图2
2) 页式管理的地址映射
首先要说明的是页式管理完全可以在没有段式管理的基础上实现,但是为了实现保护模式和以前的内存管理模式相兼容,才不得不在段式管理的基础上实现页式管理。
这样由段式管理而映射出的线性地址(没有页式管理前即为“物理地址”)就和以前由段式管理映射出的物理地址含义不同了。线性地址的具体含义如下:
typeded struct
{
unsigned int dir:10; // 表示页面表目录的下标,该目录指向一个页面表
unsigned int page: 10; // 表示页面表的下表,该表项指向一个物理页面
unsigned int offset:12; // 在4K字节物理页面内的偏移量
}线性地址
下面详细说明页式管理的内存映射过程:
a) 在CR3寄存器中取得页面目录的基地址。
b) 以线性地址中的dir项为下标,在目录中取得相应页面表的基地址
c) 以线性地址中的page项为下标,在所得的页面表中取得相应的页面描述项。
d) 将页面描述项中给出的页面基地址与线性地址中的offset项相加得到物理地址。