实模式和保护模式的中的地址
- 在实模式下,“段基址+段内偏移地址”经过段部件的处理,直接输出的就是物理地址,CPU可以直接用此地址访问内存。
- 而在保护模式下,“段基址+段内偏移地址”称为线性地址。段基址通过选择子获取,它本质是个索引,类似于数组下标,通过这个索引便能在GDT中找到相应的段描述符,在该描述符中记录了该段的起始、大小等信息,这样便得到了段基址。
- 若没有开启地址分页功能,线性地址就被当作物理地址来用,可直接访问内存。若开启了分页功能,此线性地址又多了一个名字,就是虚拟地址(虚拟地址、线性地址在分页机制下都是一回事)。虚拟地址要经过CPU页部件转换成具体的物理地址,这样CPU才能将其送上地址总线去访问内存。
- 无论在实模式或是保护模式下,段内偏移地址又称为有效地址,也称为逻辑地址,这是程序员可见的地址。
实模式
实模式下用户程序可以直至访问任意内存,存在风险
保护模式
-
与实模式相比, 保护模式中,段寄存器保存的再也不是段基址,而是选择子。该选择子其实就是一个数,用来索引全局描述符表(GDT)中的段描述符,全局描述符表就像数组,选择子就像下标一样。
全局描述符表中,每一个表项是段描述符,大小为64位。全局描述符表保存在内存中,由GDTR寄存器指向它。
-
段描述符保存在内存中,CPU访问效率不高,为提高段信息获取效率,将段信息用段描述符缓冲寄存器来缓存
寄存器扩展
除段寄存器外,从16位寄存器,扩展为32位
寻址扩展
address find.png段描述符
segment.png-
段界限
段界限
的单位,由G
指定,G
= 0表示为1字节,G
= 1 表示 4K段界限是一个偏移量,从0算起,所以实际的段界限界值 = (描述符中段界限 + 1)* (1 : 4K) - 1
根据段的扩展方向(栈向下扩展),当段内偏移超出界限范围时,被认为时非法访问。
-
段基址
3处段基址组合成一个32位的段基址
-
S
CPU将一个段描述符分为两类,系统段的描述符和数据段的描述符,由
S
位决定是否是系统段系统段:硬件运行需要用到的东西
数据段:软件用到的东西(包括,代码、数据、栈等)
S = 0 表示系统段, 1 表示数据段
-
type
与S字段共同确定段描述符的确切类型
-
DPL(Descriptor Privilege Level)
描述符特权级,代表所指内存段的特权级,能表示4中特权,0、1、2、3,数字越小权限越大。用户程序通常处于3特权级
-
P(Present)
若段存在于内存中,P = 1,否则为0。
-
AVL(Available)
表示操作系统可随意使用
-
L
用来设置是否是64位代码段
-
D/B
指示有效地址(段内偏移)和操作数的大小,用来兼容80286的保护模式(286保护模式下,操作数是16位)
对于代码段,此位是D位,D = 0表示指令中的有效地址和操作数是16位,D = 1 表示32位
对于栈段,此位是B位,B = 0表示栈的起始地址是16位寄存器的最大范围0xffff。 B = 1栈的起始地址是32位寄存器的最大寻址范围,0xffffffff。
-
G (Granularity)
指定段界限的单位大小。
G
= 0表示为1字节,G
= 1 表示 4K
全局描述符表GDT、局部描述符表LDT和选择子
GDT (Global Descriptor Table)
全局描述符表中,每一个表项是段描述符,大小为64字节。全局描述符表保存在内存中,由GDTR寄存器指向它。
GDT.png使用lgdt 指令初始化gtdr。
选择子
在保护模式中,段寄存器CS、DS、ES、FS、GS、SS不在存放段基址,而是存放一个选择子,通过选择子在GDT中找到对应的段描述符,获取段相关信息。
GDT Selector.png选择子结构:
-
RPL
请求特权级,可以表示0、1、2、3四种特权级
-
TI(Table Indicator)
用来指示选择子实在GDT中,还是LDT中索引描述符。
TI = 0表示GDT
TI = 1表示LDT
-
描述符索引值
索引值表示在GDT或LDT中的索引
LDT (Local Descriptor Table)
厂商为在硬件一级原生支持多任务而创造的表,一个任务对应一个LDT,保存任务的私有内存段。 每个任务都有自己的LDT,随着任务的切换,也要切换相应的LDT。
现代操作系统很少有用到LDT的。
打开A20地址线
在实模式下,通过段基址 * 16 + 段内偏移地址
寻址,实模式下寄存器都是16位,所以最大寻址地址为:0xffff:ffff
即0xffff0 + 0xffff = 0x10ffef
,由于8086/8088的地址线是20位(A0 ~ A19)
,最大寻址空间为1MB,即0x00000~0xfffff
。
由于没有A20
地址线,当段基址 * 16 + 段内偏移地址
超过最大寻址空间时,相当于丢掉进位,回到低地址范围。为兼容与8086/8088,在实模式下,后续的CPU都关闭A20地址线,实现地址回绕。
要进入保护模式去访问更大的内存空间,需打开A20地址线
打开A20地址线,只需要将端口0x92的第一个位置置1:
in al, 0x92
or al, 00000010b
out 0x92, al
保护模式开关
通过将控制寄存器CR0
的第0位,即PE(Protection Enable)位置1,开启保护模式
mov eax, cr0
or eax, 0x00000001
mov cr0, eax
网友评论