初识保护模式

保护模式

概括

寄存器扩展

link

在保护模式中,段寄存器中保存的再也不是段基址了,里面保存的内容叫“选择子”,selector,该选择子其实就是个数,用这个数来索引全局描述符表中的段描述符。

空间大了,内存访问的速度对CPU来说就有些低了,为了提高效率,又要提到计算机组成原理的老爱考对象:缓存(Cache)了。这里提问一下,Cache的本质原理是什么?局部性原理。

段描述符缓冲寄存器(Descriptor Cache Registers):80286的保护模式中,为了提高获取段信息的效率,对段寄存器率先应用了缓存技术,将段信息用一个寄存器来缓存。当然,在实模式下时,段基址左位后的结果就被放入段描述符缓冲寄存器中,以后每次引用一个段时,就直接走段描述符缓冲寄存器,直到该段寄存器被重新赋值。

在这里插入图片描述

寻址扩展

在这里插入图片描述

所有 32 位的通用寄存器都可以是基址寄存器;除 esp 之外的所有 32 位通用寄存器可以是变址寄存器,偏移量由实模式的 16 位变成了 32 位。并且,还可以对变址寄存器乘以一个比例因子,注意比例因子,只能是 1、2、4、8

模式反转

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

指令扩展

绝大多数指令支持3种宽度的操作数,即8位、16位、32位。

对于 loop 指令,实模式下要用 cx 寄存器来存储循环次数,在保护模式下,要用 ecx 。

mul 指令是无符号数相乘指令,指令格式是 mul 寄存器/内存。
其中“寄存器/内存”是乘数。
如果乘数是 8 位,则把寄存器 al 当作另一个乘数,结果便是 16 位,存入寄存器 ax。
如果乘数是 16 位,则把寄存器 ax 当作另一个乘数,结果便是 32 位,存入寄存器 eax 。
如果乘数是 32 位,则把寄存器 eax 当作另一个乘数,结果便是 64 位,存入 edx:eax,其中 edx 是积
的高 32 位,eax 是积的低 32 位。
有符号数相乘指令 imul 也是一样,不再说明。

对于无符号数除法指令 div,其格式是 div 寄存器/内存,其中的“寄存器/内存”是除法计算中的除数。
如果除数是 8 位,被除数就是 16 位,位于寄存器 ax 。所得的结果,商在寄存器 al ,余数在寄存器 ah 。
如果除数是 16 位,被除数就是 32 位,被除数的高 16 位则位于寄存器 dx ,被除数的低 16 位则位于
寄存器 ax。所得的结果,商在寄存器 ax,余数在寄存器 dx 。
如果除数是 32 位,被除数就是 64 位,被除数的高 32 位则位于寄存器 edx ,被除数的低 32 位则位于
寄存器 eax ,所得的结果,商在寄存器 eax ,余数在寄存器 edx 。

push压栈
立即数入栈

在实模式环境下:
当压入 8 位立即数时,由于实模式下默认操作数是 16 位,CPU 会将其扩展为 16 位后再将其入栈,sp-2。
当压入 16 位立即数时,CPU 会将其直接入栈,sp-2。
当压入 32 位立即数时,CPU 会将其直接入栈,sp-4。

在保护模式下:

当压入 8 位立即数时,由于保护模式下默认操作数是 32 位,CPU 将其扩展为 32 位后入栈,esp 指针减 4。
当压入 16 位立即数时,CPU 直接压入 2 字节,esp 指针减 2。
当压入 32 位立即数时,CPU 直接压入 4 字节,esp 指针减 4。

在这里插入图片描述

寄存器入栈

对于段寄存器的入栈,即 cs、ds、es、fs、gs、ss,无论在哪种模式下,都是按当前模式的默认操作数大小压入的。例如,在 16 位模式下,CPU 直接压入 2 字节,栈指针 sp 减 2。在 32 位模式下,CPU 直接压入 4 字节,栈指针 esp 减 4。

实模式下每次压入一个段寄存器,栈指针 sp 都会减 2。

在这里插入图片描述

保护模式下每次压入一个段寄存器,栈指针 esp 都会减 4。

在这里插入图片描述

对于通用寄存器和内存,无论是在实模式或保护模式:
y 如果压入的是 16 位数据,栈指针减 2。
y 如果压入的是 32 位数据,栈指针减 4。

在这里插入图片描述

在这里插入图片描述

全局描述符

在这里插入图片描述

这里可以看书第 150 页。

TYPE字段

下表需要和 S 字段一起使用,type 字段是要和 S 字段配合在一起才能确定段描述符的确切类型,只有 S 字段的值确定后,type 字段的值才有具体意义。

什么是系统段?各种称为“门”的结构便是系统段,也就是硬件系统需要的结构,非软件使用的,如调用门、任务门。简而言之,门的意思就是入口,它通往一段程序。关于系统段这里咱们不再多说,目前主要是关注 S 为 1 时,非系统段的 type 子类型。

在这里插入图片描述

全局描述符表、局部描述符表和选择子

在这里插入图片描述

在这里插入图片描述

由于段寄存器是 16 位,所以选择子也是 16 位,在其低 2 位即第 0~1 位,用来存储 RPL,即请求特权级,可以表示 0、1、2、3 四种特权级。在选
择子的第 2 位是 TI 位,即 Table Indicator,用来指示选择子是在 GDT 中,还是 LDT 中索引描述符。TI为 0 表示在 GDT 中索引描述符,TI 为 1 表示在 LDT 中索引描述符。选择子的高 13 位,即第 3~15 位是描述符的索引值,用此值在 GDT 中索引描述符。

A20 地址线

在这里插入图片描述

如果 A20 Gate 被禁止,当访问 0x100000~0x10FFEF 之间的地址时,CPU 将采用 8086/8088 的地址回绕,如上图。

如果 A20 Gate 被打开,当访问到 0x100000~0x10FFEF 之间的地址时,CPU 将真正访问这块物理内存。

; 打开 A20 地址线的方式
in al,0x92Asm
or al,0000_0010B
out 0x92,al

CRx 控制寄存器

控制寄存器是 CPU 的窗口,既可以用来展示 CPU 的内部状态,也可用于控制 CPU 的运行机制。这里我们要用到的是 CR0 寄存器。

在这里插入图片描述
在这里插入图片描述

; 将 CR0 的PE位置 1
mov eax, cr0
or eax, 0x0000_0001
mov cr0, eax

内存段保护

向段寄存器加载选择子时的保护
检查越界

在这里插入图片描述

描述符表基地址+选择子中的索引值*8+7 <=描述符表基地址+描述符表界限值

检查段类型

这里先截取表 4-10的下半部分

在这里插入图片描述

详细的检查表 别背,需要时回来查表

在这里插入图片描述

检查段是否存在

CPU 通过段描述符中的 P 位来确认内存段是否存在,如果 P 位为 1,则表示存在,这时候就可以将选择子载入段寄存器了,同时段描述符缓冲寄存器也会更新为选择子对应的段描述符的内容,随后处理器将段描述符中的 A 位置为 1,表示已经访问过了。如果 P 位为 0,则表示该内存段不存在,不存在的原因可能是由于内存不足,操作系统将该段移出内存转储到硬盘上了。这时候处理器会抛出异常,自动转去执行相应的异常处理程序,异常处理程序将段从硬盘加载到内存后并将 P 位置为 1,随后返回。CPU 继续执行刚才的操作,判断 P 位。

代码段和数据段的保护

实际段界限的值为:
(描述符中段界限+1)*(段界限的粒度大小:4 KB 或者 1 字节)-1。
对于 G 位为 1 的 4 KB 粒度大小的段来说,其实用下面这个公式更为直接。实际段界限大小 = 描述符中段界限 * 0x1000+0xFFF
其中,0xFFF 是 4 KB(0x1000)中以 0 为起始的最后一字节。所以此公式的意义是以 0 为起始的段偏移量,即段界限。推导过程也很简单,就是将原公式展开:(描述符中段界限+1)* 4 KB - 1= 描述符中段界限 * 4 KB + 4 KB - 1 = 描述符中段界限 * 0x1000 + 0xFFF

偏移地址 + 数据长度 - 1 ≤ 实际段界限大小

栈段的保护

对于向上扩展的段,实际的段界限是段内可以访问的最后一字节。
对于向下扩展的段,实际的段界限是段内不可以访问的第一个字节。

在这里插入图片描述

进入保护模式

  1. 打开 A20 地址线。
  2. 加载 GDT 。
  3. 将 CR0 的 PE 位置 1。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值