intel 8086是16位的CPU,有着16位的寄存器,16位的数据总线和20位的地址总线。但由于其寄存器和数据总线都是16位,仅仅具有64kb的寻址能力,所以采用段+偏移的方式得到20位的即1M的寻址能力。则其计算公式为:
物理地址 = 段值 * 16 + 偏移。
也就是段值左移一位 + 偏移。 —其中,段值和偏移都是16位的
但80386开始,CPU进入32位时代,其具有32位地址线,所以寻址能力变为4G。寻址空间虽然变大了,但是依然采用“段:偏移”的形式,但是具体的策略却发生了变化。
在实模式下,段值还可以看成是地址的一部分,段值仅仅就是左移一位,然后加上偏移地址就是实际的物理地址;但是在保护模式下,段值仅仅变成了一个索引,该索引指向一个数据结构的一个表项,表项记录着段的基址,段界限,以及属性等内容,该数据结构就是GDT。GDT中的一个表项就是段描述符(Descriptor)。
下面是段描述符的一个结构图:
属性的详细了解:
(1):P:存在位
P=1 表示描述符对地址转换是有效的,或者说该描述符所描述的段存在,即在内存中
P=0 表示描述符对地址转换无效,即该段不存在,使用该描述符进行内存访问时会引起异常
(2):DPL: 描述符特权级(Descriptor privilege level).共2位。规定了描述段的特权级,用于特权检查,以决定对该段能否访问。
(3):S: 描述符的类型
对于存储段描述符,S=1系统段描述符和门描述符,S=0
(4):TYPE: 说明存储段描述符所描述的存储段的具体属性
(5):G: 段界限粒度位(Granularity)
G=0: 表示段界限粒度位字节
G=1: 表示段界限粒度为4k字节
注意:界限粒度位只对段界限有效,对段基址是无效的,段基址总是以字节为单位。
(6): D位
D位是一个很特殊的位,在描述可执行段、向下扩展数据段或由SS寄存器寻址的段(通常是堆栈段)的三种描述符中的意义各不相同。
⑴ 在描述可执行段的描述符中,D位决定了指令使用的地址及操作数所默认的大小。
① D=1表示默认情况下指令使用32位地址及32位或8位操作数,这样的代码段也称为32位代码段;
② D=0 表示默认情况下,使用16位地址及16位或8位操作数,这样的代码段也称为16位代码段,它与80286兼容。可以使用地址大小前缀和操作数大小前缀分别改变默认的地址或操作数的大小。
⑵ 在向下扩展数据段的描述符中,D位决定段的上部边界。
① D=1表示段的上部界限为4G;
② D=0表示段的上部界限为64K,这是为了与80286兼容。
⑶ 在描述由SS寄存器寻址的段描述符中,D位决定隐式的堆栈访问指令(如PUSH和POP指令)使用何种堆栈指针寄存器。
② D=1表示使用32位堆栈指针寄存器ESP;
② D=0表示使用16位堆栈指针寄存器SP,这与80286兼容。
(7):AVL:软件可利用位
下面学习一下段选择子,首先段选择子不是刚刚所说的那个索引,段选择子为16为,其中13位为描述符索引,一位TI位,两位RPL位。
TI:(table Indicator): 引用描述符表指示位
TI = 0 : 指示从全局描述符表GDT中读取描述符
TI =1:指示从局部描述符表LDT中读取描述符
RPL(requested Privilege level): 请求特权级,用于特权检查
现在使用一张图描述一下段存储机制的寻址过程。