上篇写了从实模式进入到保护模式,现在我们简单写一下怎么返回到实模式
代码如下:
LABEL_REAL_ENTRY: ; 从保护模式跳回到实模式就到了这里
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, [SPValueInRealMode]
in al, 92h ;
and al, 11111101b ; 关闭 A20 地址线
out 92h, al ;
sti ; 开中断
mov ax, 4c00h ;
int 21h ; 回到dos
这个代码就不做过多解释了,接下来我描述些保护模式与实模式概念,分点来说明:
什么是实模式,什么是保护模式
实模式:32位微处理器只使用其中的低20位地址线A19-A0来寻址内存,因此最大寻址的物理空间空间为1MB。段地址和段偏移量都使用16位数来表示,每段存储器的最大容量为64KB。也就是说是CPU通过实际地址查找数据,实际地址也就是物理地址。(段首地址+段偏移)
保护模式:主要用于多任务环境下。所谓保护就是对被切换任务所使用的存储器内容进行保护。在保护模式下存储器的地址采用虚拟地址、线性地址、物理地址三种方式来描述,需要通过一种称为描述符表的数据结构来实现对内存单元的访问。(也就是上篇中通过选择子做为索引,然后根据GDTR中存放着段描述符表的首地址,就能找到对应的段描述符,段描述符中有段的物理首地址,就得到段在内存中的首地址,加上偏移量,就找到在这个段中存放的数据的真正物理地址)
那么GDT,描述符,选择子它们又是什么关系
在上个问题中,已经讲述了保护模式下,分段机制是利用一个称作段选择符的偏移量,从而到描述符表找到需要的段描述符,而这个段描述符中就存放着真正的段的物理首地址,再加上偏移量。认识一下段描述符:一个结构体,它有三个成员变量:1、段物理首地址 2、段界限 3、段属性
而描述符表,是一个数组,是一个段描述符组成的数组。段选择子,也就是数组的索引,是我们将要找的那个段描述符相对于数组首地址(也就是全局描述表GDT的首地址)偏移位置。
也就是说:通过Selector(段选择子)找到存储在Descriptor Table(描述符表)中某个Descriptor(段描述符),该段描述符中存放有该段的物理首地址,所以就可以找到内存中真正的物理段首地址Segment。最后加上偏移量就能找到物理地址。
最后我们讲讲GDTR:中文是全局描述表寄存器,段描述符表存放在内存中,那CPU是如何知道它在哪里呢?于是就设计了一个全局描述符表寄存器,专门用来存放段描述符表的首地址,以便找到内存中段描述符表。