主要是写给同我一样陷入误区的童鞋,语文没学好啊,看不清楚就网上搜搜资料,我刚都找到了个很详细的,不过叉了后又找不到了。
以前记忆中对windows保护模式寻址方式的认识就是,描述符表+段选择子+偏移量=物理地址。描述符表由GDTR寄存器提供,段选择子保存在段寄存器中,每个线程环境保存切换时更新,偏移量就不清楚谁提供了,也不清楚当执行指令 jmp 地址,是怎样跳转的。当时觉得不用深究,知道就行了。
然后今天读天书夜读12章,发现根本就不是这样额,别个根本就没有提到什么描述符表,段选择子,然后知道了保护模式也分平坦模式,多段模式,有些地方看到是分页模式,分段模式,原来intel80x86 支持这2种寻址方法,而windows用的就是分页模式,网上一搜大多是段选择子什么的,也没看明白这种寻址方式到底如何工作,那位大哥能具体讲解下不。
分页模式就简单多了,windows和linux都工作在这种模式下,说说我的理解,虚拟内存(每个进程的4GB空间)和物理内存都被分成一页一页的,每页4KB。每个进程维护一个页目录表,保存在一个4kb的物理内存页中,cr3寄存器保存它的基地址,每个页目录的项又指向一个页表,一个页表还是只占一个页(4kb空间),页表的每一项才指向4kb的物理地址页。
哎,解释好辛苦,怪不得别人问总爱答不解释。
举例: jmp 01010100101010101010101010101010 (2进制32位地址)
前十位用来寻址页目录
中十位用来寻址页表
后12位是地址偏移。
位什么是10位,10位,12位呢。应为页目录表的项,和页表的项都是4个字节,4KB除以4页就是有1024项,2的10次方页等于1024,所以10位就足够寻址了。每个页4kb,所以12位地址偏移刚好。
cr3提供基地址+0101010010(前10位)*4(每项4字节) 得到页目录项32位(4字节)
页目录项的32位是页表项的地址 + 1010101010(10位)*4 得到页表项地址
页表项的前20位用来寻址物理地址,后面的12位纪录页的一些属性。
前20位*4*1024(左移12位)+101010101010(12位的地址偏移) = 物理地址
1024(页目录表)*1024(页表)*4*1024(每页4KB) = 4GB。 刚好等于虚拟地址空间大小。
添加:
我说的只是自己的理解,仅供参考啊
刚才看80x86汇编语言程序设计的第10章发现我又错了,362页有个图,我画不来就用文字表达:
选择子:偏移量 -》【分段管理机制】-》线性地址-》(可选)【分页管理机制】-》物理地址。
可以选择用不用分页管理机制,不用的话 线性地址就直接等于物理地址。
偏移量经常就是虚拟地址,这时选择子所对应的全局描述附表中的存储段描述符不可用(猜的,也有可弄为0),所以偏移量就等于线性地址了。如果可用的话 线性地址=存储段描述符中的基地址 + 偏移。
说说线性地址,物理地址,虚拟地址,逻辑地址。
baidu百科说:线性地址(Linear Address)也叫虚拟地址(virtual address)是逻辑地址到物理地址变换之间的中间层
80x86汇编说:段是实现虚拟地址到线性地址转换的基础。
这几爷子啊,怪不得以前要晕。 我还是当逻辑地址这概念不存在;
虚拟地址好理解就是每个进程虚拟出来的4GB空间,物理地址就是真实地址。
线性地址是中间层,它设计出来就是为了把2维的虚拟地址空间变成线性的就是一维的吧,我是这样理解2维的:同一个地址存在无数个(因为有无数个进程每个进程一个这地址)。
但是大多时候线性地址 = 虚拟地址(选择子不存在时),我认为在这个时候应该没有线性地址的,虚拟地址没转换成线性地址而是直接转换成了物理地址,不存在中间层。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!