1)在保护模式下改变段寄存器的功能,使其从一个单纯的基地址变成向这样一个数据结构的指针。
这样,当一条访问内存的指令发出一个内存地址时,cpu就可以这样来归纳出实际应该放上数据
总线的地址:
a.根据指令的性质来确定应该使用哪一个段寄存器,例如转移指令中的地址在代码段。
b.根据段寄存器的内容,找到相应的‘地址段描述结构’。
c.从地址段描述结构中得到基地址。
d.将指令中发出的地址作为位移,与段描述结构中规定的段长度相比,看看是否越界。
e.根据指令的性质和段描述符中的访问权限来确定是否越权。
f.将指令中发出的地址作为位移,与基地址相加而得出实际的‘物理地址’。
具体的汇编代码因为懒惰就不配,暂时以脑补为主吧。
2)全局性段描述表寄存器GDTR,局部性段描述表寄存器LDTR.
分别可以用来指向存储在内存中的一段描述结构数组,成为段描述表。
访问这两个寄存器的专用指令设计成“特权指令”。
3)将段寄存器内容的低3位屏蔽掉以后与GDTR或LDTR中的基地址相加得到描述表项的起始地址。
4)段描述结构:
typedef struct {
unsigned int base24_31 : 8; //基地址的最高8位
unsigned int g : 1; //granularity,表段的长度单位,
//0表示字节,1表示4kb。
unsigned int d_b : 1; //defalut operation size存取方式
//0=16位,1=32位。
unsigned int unused : 1; //固定设置成0
unsigned int av1 : 1; //avalable,可供系统软件使用
unsigned int seg_limit 16_19 : 4; //段长度的最高4位
unsigned int p : 1; //segment present,为0时表示该段的内容不在内存中
unsigned int dpl : 2; //descriptor privilege level,访问本段所需权限
unsigned int s : 1; //描述项类型,1系统,0代码或数据
unsigned int type : 4; //段的类型,与上面的s标志位一起使用
unsigned int base_0_23 : 24; //基地址的低24位
unsigned int seg_limit_0_15 : 16; //段长度的低16位
unsigned short seg_idx : 13; //13位的段描述项下标
unsigned short ti : 1; //段描述表指示位,0表示GDT,1LDT
unsigned short rpl : 2; //Requested privilege level,要求的优先级
}