x86三种模式:
实模式:x86处理器被复位或加电启动时,寻址方式:段寄存器×0x10+偏移地址,偏移地址0~4KB,单任务,所有指令使用物理地址,运行在同一内存空间。
保护模式:CR0的控制位PE置0实现,使用线性地址,多任务,支持虚拟内存,应用程序运行在ring3,操作系统运行在ring0,分属用户地址空间和内核地址空间。
虚拟x86模式:兼容8086程序,在保护模式下模拟出的实模式。
分段机制
保护模式下,CPU将内存空间划分为受保护的区域,每个区域成为一个段,并使用段描述符(SD为8字节)记录内存的基本属性:段的基地址和边界,是否在内存中,段类型等。
系统中存在多任务,每个任务涉及多个段,因而产生了段描述符表:GDT,LDT及IDT。
GDT:全局描述符表,只有一个,包含操作系统使用的代码段,数据段,堆栈段的SD以及各任务的LDT段。
LDT:局部描述符表,每个任务对应一个,包含任务的私有代码段,数据段,堆栈段的SD,以及门SD。
IDT:中断描述符表,每个CPU对应一个。
GDTR寄存器,IDTR寄存器均为48位,高32位对应表的基地址,低16位对应边界;
LDTR寄存器位16位,表示当前任务的LDT表在GDT中的索引,其格式是典型的段选择子格式:高13位为SD索引,TI位=0表示GDT,TI位=1表示LDT。低2位表示程序的RPL。此外TR也存放selector,指向的是GDT中描述当前TSS的SD。
保护模式下的异常或中断发生时,CPU根据IDTR得到ID的地址,取出n号门描述符,从 描述符中得到中断服务程序的地址xxxx:yyyyyyyy,进过段地址转换后得到服务程序的32位线性地址并转移执行。
注:门指向某个优先级高的程序所规定的入口点,所有优先级低的程序调用优先级高的程序只能通过门重定向,进入门所规定的入口点。有中断门,自陷门和任务门。
对于保护模式下的分段地址xxxx:yyyyyyyy,以下介绍如何映射为线性地址,其中xxxx为selector(CS,DS,ES,FS,GS,SS)。
首先判断前任务的selector的TI位是否为0:
(1)若为0,则从GDTR中获取GDT的基址,然后在GDT中以selector的高13位为索引,得到SD,进而获取分段地址的各种属性,包括基址,长度,优先级等。
(2)若为1,则从GDTR中获取GDT的基址,然后在GDT中以LDTR的高13位为索引,得到LDT所在段的位置,然后在LDT中以selector的高13位为索引,得到SD,进而获取分段地址的各种属性,包括基址,长度,优先级等。
基址+偏移地址 = 线性地址
分页机制
若分页机制未启用,则线性地址=物理地址,否则线性地址≠物理地址。
分页机制的优势:分页机制并非实现虚拟内存的必要条件(使用内存映射文件,写时复制才是实现虚拟内存的机制),其主要作用解决分段机制单位过大造成的内存碎片化问题。
PD:存放PDE即PT的线性表,占用4KB内存页,每个PDE为32位,高20位表示PT的起始物理地址的高20位,即PT位4KB边界对齐。低12位表示PT的属性,包括特权级别,访问属性,读写权限,是否在物理内存中。
PT:存放PTE的线性表,占用4KB内存页,每个PTE为32位,高20位表示内存页的其实物理地址的高20位,即4KB内存页4KB边界对齐(2M,4M大内存页不使用PT)。低12位表示内存页的属性。
CR3寄存器:页目录基地址寄存器PDBR,高20位表示页目录的基地址,即PD按照4KB边界对齐。
以下介绍线性地址到物理地址的映射:
1.通过CR3寄存器获取PD的基地址,在PD中以线性地址的高10位为索引,获取PDE;
2.通过PDE获取PT的基地址,在PT中以线性地址的12~21位作为索引,获取PTE;
3.通过PTE获取内存页的基地址,加上线性地址的低12位,得到物理地址。
对于4M大内存页,PDE的高10位+线性地址的低22位,得到物理地址。
利用windbg手动将线性地址转换位物理地址的方法(以进程A中的某一地址t为例)
1.进入本地内核调试lkd,输入!process 0 0命令,列出所有进程,找到A的内容
2.找到DirBase,即页目录基地址的物理地址x,根据地址t获取页目录索引k1,输入!dd x,则第k项的高20位即为PDE的基地址y
3.根据地址t获取页表索引k2,输入!dd y + k2*4,则获得内存页的基地址,再加上偏移地址即得物理地址。
附:windbg物理地址相关命令
dg:显示段选择子所指向的段描述符信息
!pte:显示页目录和页表的地址
!vtop:将虚拟地址翻译为物理地址
!vpdd:显示物理地址,虚拟地址和内存的内容
!ptov:显示指定进程中所有物理内存到虚拟内存之间的映射
!sysptes:显示系统的页目录表项。