保护模式
实模式与保护模式的区别
实模式
实模式出现于早期8088 CPU时期。当时由于CPU的性能有限,一共只有20位地址线,地址空间只有2^20B = 1MB,以及8个16位的通用寄存器,以及4个16位的段寄存器 ES、SS、CS、DS。为了能够通过这些16位的寄存器去构成20位的主存地址,必须采取特殊的方式。
格式:段基址:偏移
段基址 << 4 + 偏移 = 物理地址
保护模式
由于实模式并未考虑安全、多任务支持、CPU特权模式等问题,随便一个程序都能修改别人的内存。在保护模式中,每个人只能访问自己的内存,高任务级别可以访问低级别的内存等功能。保护模式实现了更大的空间,更灵活也更安全的内存访问,其寻址方式还是段基址+偏移地址(兼容),不过段基址不放在段寄存器,而是开一个GDT表,即全局描述表,把段的基址、还有这个段的其它一些信息(权限等)存到这个表中。全局描述符表中含有一个个表项,每一个表项称为段描述符。而段寄存器在保护模式下存放的便是相当于一个数组索引的东西,通过这个索引,可以找到对应的表项。段描述符存放了段基址、段界限、内存段类型属性(比如是数据段还是代码段,注意一个段描述符只能用来定义一个内存段)等许多属性。
实际段界限边界值=(描述符中的段界限+1) x (段界限的单位大小(即字节或4KB)) - 1,如果偏移地址超过了段界限,CPU会抛出异常。
全局描述符表位于内存中,需要用专门的寄存器指向它后, CPU 才知道它在哪里。这个专门的寄存器便是GDTR(一个48位的寄存器),专门用来存储 GDT 的内存地址及大小。
struct GDTR{ //全局描述符表
DWORD base;
WORD limit;
}
段的选择子
段寄存器 CS、 DS、 ES、 FS、 GS、 SS,在实模式下时,段中存储的是段基地址,即内存段的起始地址。而在保护模式下时,由于段基址已经存入了段描述符中,所以段寄存器中再存放段基址是没有意义的,在其中存入的是选择子。选择子基本上
是个索引值,但也还有其他内容。由于段寄存器是 16 位,所以选择子也是 16 位,在其低 2 位即第 0~1 位, 用来存储 RPL,即请求特权级,可以表示 0、 1、 2、 3 四种特权级。实际上保护模式下还支持了内存的分页基址,把这个地址分成页表、页目录、偏移量,然后再去找对应的数据,最后再组合起来变成物理地址。
选择子的第 2 位是 TI (Table Indicator) 位,用来指示选择子是在 GDT 中,还是 LDT 中索引描述符。 0 = 在 GDT 中索引描述符, 1 = 在 LDT 中索引描述符。由于Windows没有LDT,所以TI始终为0。
选择子的高 13 位,即第 3~15 位是描述符的索引值,(此值 << 3) + GDTR中获取的基址就是当前要取的项。
Windbg配置
虚拟机串行端口命名:\\.\pipe\com_1
C:\boot.ini文件添加:multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional_debugf(10-10-12)" /noexecute=optin /fastdetect /debug /debugport=com1 /baudrate=115200
该文件为隐藏文件,需要先取消隐藏才能编辑
cmd启动windbg:windbg.exe -b -k com:pipe,port=\\.\pipe\com_1,baud=115200,reconnect -y
如果看不到寄存器的值,放入wingdbg.dll到windbg.exe同目录下,执行!WingDbg.regfix
,重新打开寄存器窗口