保护模式入门
地址转换是由处理器和操作系统共同协作完成的,处理器在硬件上提供地址转换部件,操作系统提供转换过程中所需要的页表。
保护模式概述
寄存器拓展
实模式的CPU运行环境是16位,保护模式的运行环境是32位的。为了寻址4GB的内存空间(段基址:段内偏移地址),将除了段寄存器(16位够用)之外的寄存器(通用寄存器,指令指针寄存器,标志寄存器都变为32位)。
在保护模式下,段基址与实模式不同,为了安全,添加了一些约束条件——对内存段的描述信息,由于信息太多,寄存器无法存放,所以使用全局描述符表(大)来存放。表中的每一个表项称为段描述符,大小为64字节,用来描述各个内存段的起始地址、大小、权限等信息,放在内存里面,由GDTR寄存器指向它。
段寄存器保存的不再是段基址,而是选择子,selector(其实就是一个数,用这个数来索引全局描述符表的段描述符(在内存中),就像数组的下标),段描述符缓冲寄存器用来缓存内存中的段描述符。
寻址拓展
指令拓展
对于段寄存器的入栈(cs/ds/es/fs/gs/ss),16位模式下压入2字节,32位模式下压入4字节。对于通用寄存器和内存,无论是在实模式或者保护模式下,如果压入的是16位的数据,栈指针减2;如果压入的是32位的数据,栈指针减4.
全局描述符表
段描述符
段描述符是连续的8字节大小,保护模式下,地址总线宽度是32位,所以段基址需要用32位地址表示。段界限(20个二进制位表示)表示段边界的拓展最值,即最大或最小拓展到多少,方向只有向上或向下,对于代码段和数据段,段的拓展是向上,即地址越来越高,表示段内偏移的最大值;对于栈段,拓展方向是向下,此时表示段内偏移地址的最小值。段界限只是单位量,单位是字节或者是4kb,由描述符中的G来指定,所以段的大小只能为2的20次方=1MB或者2的32次方=4GB,因为计算机从0开始,所以实际的段界限边界值=(描述符中的段界限+1)*(段界限力粒度4kb或1b)-1。
若G处为0,则段界限单位为1B,G处为1,则单位为4KB字节。
对于高32位处,第12位是显示是否为系统段。凡是在硬件运行需要的东西成为系统,称为系统段为0,软件(包括操作系统)需要的称为数据段为1(代码段在段描述符中也属于数据段)8-11是type字段,用来指定本描述符的类型
表中的A位表示Accessed位,由CPU设置,每当该段被CPU访问过就设置为1。C是一致性代码段,指如果自己是转移的目标段,并且是一致性代码段,则自己的特权级一定高于当前特权级。E表示拓展方向,0表示向上,1表示向下。
段描述符中的第13-14位是DPL字段,Descriptor Privilege Level,描述符特权级,分为0-1-2-3级特权,数字越小特权级越大。第15位是P字段,Present,即段是否存在,如果段存在与内存中,P为1,否则为0。第20位为AvaiLable,可用,对操作系统无效;第21位L字段,是否是64位代码段,对要实现的操作系统无效(32位)。
第22位是D/B字段,指定操作数和有效地址的大小(为了兼容16位),对于代码段是D字段,0-16-使用IP寄存器,1-32-使用EIP寄存器;对于栈段,此为B,0-16-sp寄存器,1-32-esp寄存器
全局描述符表GDT
多个程序都可以在里面定义自己的段描述符,由GDTR(GDT Register)寄存器(48位,存储内存地址 32位及大小16位)指向GDT,使用lgdt指令访问,每个描述符大小8字节,GDT最多有8192个段或门。使用选择子selector(16位)访问GDT某个特定的地址,相当于索引,第0-1位用来存储4个特权级,第2位是TI位,Table Indicator,用来表示选择子在GDT还是LDT(局部描述符表Local,lldt指令,很少用)中,选择子索引部分13位,正好是8192个。
进入保护模式后,已经是32位地址线和32位寄存器,故段基址不需要再乘16了,直接与段内偏移地址相加即可。
CR0寄存器的PE位,即第0位是保护模式的开关,若为0则代表在实模式下,1代表保护模式下运行。