从实模式到保护模式

对《X86汇编语言从实模式到保护模式》书中的部分内容进行总结。

实模式

因为早期的处理器是16位的如8086,后来处理器逐渐升级为32位的如80386,实模式的存在主要还是为了让32位处理器兼容针对16位处理器开发的程序。
处理器中代表的寄存器:
8086处理器内部组成框图
8086处理器的寄存器都是16位的,为了达到1MB的寻址空间,在寻址的时候先将段寄存器的内容左移四位形成20位的段地址,再加上16位的偏移地址得到20位的物理地址。在寻址时,通常两个寄存器搭配完成,指令段的寻址由[CS:IP]确定,数据段的寻址由[DS:偏移]确定,堆栈段的寻址由[SS:SP]确定。

保护模式

相较于8086处理器,80386处理器的寄存器扩展到32位,能够寻址4GB地址空间,所以寻址时,不再需要段寄存器的内容左移四位。在32位模式下,传统的寄存器如CS、SS、DS、ES称为段选择器,保存的不再是16位段基地址,而是段的选择子。除了段选择器之外,每个段寄存器还包括一个64位的不可见部分,称为描述符高速缓存器,里面有段的基地址和各种访问属性。这部分内容程序不可访问,由处理器自动使用。
32位处理器内的段寄存器:
32位处理器内的段寄存器

进入保护模式的准备

(1)全局描述符表GDT

全局描述符表由段描述符组成,段描述符中包含段的起始地址、段界限和其他访问属性,每个描述符占8个字节。为了确定全局描述符表的位置,处理器内部有一个48位寄存器,低16位是全局描述符表的大小(其数值等于总字节数减1),换句话说,全局描述符表的界限值就是表内最后1字节的偏移量。高32位线性基地址部分保存的是全局描述符表在内存中的起始线性地址。GDT是在进入保护模式之前定义的,由于在实模式下只能访问1MB的内存,故GDT通常都定义在1MB以下的内存范围中。当然,允许在进入保护模式之后换个位置重新定义GDT。

(2)建立GDT

  • 处理器规定,GDT中的第一个描述符必须是空描述符;
  • 安装代码段描述符;
  • 安装数据段描述符;
  • 安装栈段描述符;
  • 加载描述符表的线性基地址和界限到GDTR寄存器。

(3)使能第21条地址线A20

(4)进入保护模式

保护模式下的内存访问

段选择子的组成

在保护模式下访问一个段时,传送到段选择器(CS、SS、DS、ES)的是段选择子。它由三部分组成,第一部分是描述符的索引号,用来在描述符表中选择一个段描述符。TI是描述符表指示器(Table Indicator),TI=0时,表示描述符在GDT中;TI=1时,描述符在LDT中。LDT的知识将在后面进行介绍,它也是一个描述符表,和GDT类似。RPL是请求特权级,表示给出当前选择子的那个程序的特权级别,正是该程序要求访问这个内存段。
在这里插入图片描述

访问过程

mov cx,00000000000_10_000B         ;加载数据段选择子(0x10)
mov ds,cx

按照我们前面所说,全局描述符表的建立过程第一个表项是空,第二个表项是代码段的描述,第三个表项是数据段的描述,第四个表项是栈段的描述。0000_0000_00010_0_00其指定的描述符索引号是2,指定的描述表是GDT,请求的特权级RPL是00。GDT的线性基地址在GDTR中,又因为每个描述符占8字节,因此,描述符在表内的偏移地址是索引号乘以8。如下图所示,当处理器在执行任何改变段选择器的指令时(比如pop、mov、jmp far、call far、iret、retf),就将指令中提供的索引号乘以8作为偏移地址,同GDTR中提供的线性基地址相加,以访问GDT。处理器将选择子加载进段寄存器的选择器需要验证,如果没有发现什么问题(比如超出了GDT的界限,当然还有其他要验证的),就自动将找到的描述符加载到不可见的描述符高速缓存部分。mov cx,00000000000_10_000B把描述符选择子0x10加载到段选择器DS,并自动加载描述符高速缓存器
在这里插入图片描述
此后,每当有访问内存的指令时,就不再访问GDT中的描述符,直接用当前段寄存器描述符高速缓存器提供线性基地址。因此,上述指令中没有段超越前缀,故默认使用数据段寄存器DS。如下图所示,执行这条指令时,处理器用DS描述符高速缓存中的线性基地址加上指令中给出的偏移量0x00,形成32位物理地0x000b8000,并将字符“P”的ASCII码写入该处。

 mov byte [0x00],'P'

在这里插入图片描述

清空流水线并串行化处理器

进入保护模式后要解决下面两个历史遗留问题:

  • 在实模式下,段寄存器的描述符高速缓存器也被用于访问内存,仅低20位有效,高12位是全零。 当处理器进入保护模式后,不影响段寄存器的内容使用,它们依然是有效的,程序可以继续执行。但是,在保护模式下,对段的解释是不同的,处理器会把段选择器里的内容看成是描述符选择子,而不是逻辑段地址。因此要尽快刷新CS、SS、DS、ES、FS和GS的内容,包括它们的段选择器和描述符高速缓存器。
  • 在进入保护模式前,有很多指令已经进入了流水线。因为处理器工作在实模式下,所以它们都是按16位操作数和16位地址长度进行译码的,即使是那些用[bits 32]编译的指令。进入保护模式后,由于对段地址的解释不同,对操作数和默认地址大小的解释也不同,有些指令的执行结果可能会不正确,所以必须清空流水线。同时,那些通过乱序执行得到的中间结果也是无效的,必须清理掉,让处理器串行化执行,即重新按指令的自然顺序执行。

为了达到上述两个目的,使用32位远转移指令jmp或者远过程调用指令call。处理器最怕转移指令,遇到这种指令,一般会清空流水线,并串行化执行;另一方面,远转移会重新加载段选择器CS,并刷新描述符高速缓存器中的内容

jmp 0x0008:0x007B

进入保护模式后,第一个操作数0x0008是段选择子,而不是实模式下的逻辑段地址。在处理器执行上面代码时,可以分为几步(其实是同时进行),首先根据段选择子提供的信息,将段描述符加载进CS描述符高速缓存器,然后将指令中0x007B偏移量加载进指令指针寄存器EIP。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是浩浩子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值