(Pmtest8.asm总结)PagingDemoProc 注意这个这个程序段使用的是LinearAddrDemo线性地址。分页后线性地址要转换
PagingDemoProc:
OffsetPagingDemoProc equ PagingDemoProc - $$
mov eax, LinearAddrDemo ;LinearAddrDemo equ 00401000h ,ProcFoo equ 00401000h
call eax ;跳到foo处执行代码
retf
LenPagingDemoAll equ $ - PagingDemoProc
设计一个Flat段,尽管他的基址为0,这样做的好处是逻辑很清楚,只要用到这个段名,他们涉及到的代码和数据就都在这个段里。这样逻辑就不会混乱。
mov eax, LinearAddrDemo ;LinearAddrDemo equ 00401000h ,ProcFoo equ 00401000h
call eax
call eax时根据cr3的页目录基址,加上LinearAddDemo的变换找到真实物理地址。
我们来看看:假设cr3中放的是PageDirBase0,即200000h,这个页目录里放的PTE为201000h
00401000 转换为2进制就是:0000,0000,0100,0000,0001,0000,0000,0000
前十位0000,0000,01,是页目录偏移量,即偏移一个页目录变为200004,则这个页目录里的PTE为202000h,存放的页为400000h
中十位0000,0000,01,是页表的偏移量,即偏移一个页表,即202004h,则这个页表PTE里页为401000h
后12位是页偏移地址为0,所以最后的物理地址为401000h,正好是foo函数的地址,去执行foo函数。
可以参见pmtest6.asm 代码详细解释,即分页机制形成的详细过程这篇文章。
http://www.cnblogs.com/wanghj-dz/archive/2011/04/26/2029244.html
PSwitch函数的功能是建立好页表后,把与202004h类似的212004(由cr3不同引起的)的这个PTE里的页地址由原来的按顺序建立的00401000h,改为了00501000h,变成了bar函数的地址。这时,原来自动按顺序建立的页表就被打乱了。哈哈,妙!!
再总结:终于搞清楚了,其实真实内存地址,有一块地方或n块地方存放的是对整个内存进行分配的页表。(页表就是对内存进行分配的表)也可能不止一种分配方案啊。然后在真实物理地址写上程序,以便在页表中找到程序的物理地址,从而跳转过来执行之。