【一篇文章让你入门保护模式】

本文详细介绍了保护模式的进入步骤,包括开启A20地址线、加载全局描述符表(GDT)、设置控制寄存器CR0。保护模式旨在为多用户多任务环境提供内存隔离,通过特权级和段描述符实现。段描述符包含权限、扩展方向、粒度等信息,用于限制不同级别的程序访问资源。此外,文章还讨论了选择子、控制寄存器CR0的作用,以及A20地址线的历史与开启方法。
摘要由CSDN通过智能技术生成

保护模式

如何进入保护模式

  • 打开A20地址线
  • 加载GDT
  • 将cr0的PE位置1
  • 刷新流水线(可选)

保护模式是保护什么?

实模式下的汇编可以访问所有的资源,比如1MB的内存。亦或者任何端口,可以访问任何端口则表示可以访问所有的外设。

假如有以下代码

mov ax, 0
mov ds, ax
mov byte [0x10], 0

在实模式下,0 ~ 3FF这1KB内存保存着中断向量表,上面这段代码则会破坏中断向量表IVT,进而破坏整个电脑的运转,这显然不是用户想看见的。

诸如此类可以随意更改内存空间的代码,有心之人可以随意做到,因为在实模式下毫无限制。

在多用户多任务时代,内存中将会有多个用户程序存在,为了使每个程序彼此隔离,互不干扰,因此就有了保护模式

在保护模式中,每个程序都有一个特权级,特权级是用数字表示:0, 1, 2, 3

特权级0的权限最高,可以执行特权指令、访问所有的内存或者访问所有端口。3最低

除非使用特定的方法,否则,不同的特权级不能随意访问。

操作系统会登记所使用的段,包括段的起始地址,段界限。

GDT和GDTR

描述一个段需要8个字节,因此称之为段描述符。每个段都需要一个描述符,为了存放这些描述符号,需要一段内存空间

当所有的段描述符在一片内存中连续存在时,便形成了表,称之为描述符表

而GDT就是全局描述符表,要在进入保护模式之前先定义。为了跟踪GDT的位置,有一个特殊的寄存器称之为全局描述符表寄存器,GDTR(48位),GDTR中保存了GDT的线性地址和界限

GDTR分为两个部分,一个32位部分和16位部分,32位部分保存GDT的线性基地址,也就是GDT的起始地址,16位保存界限,在数值上为表的大小 - 1

因为这个界限是16位的,所以最多占64KB。因为一个描述符8字节,所以最多可以在GDT中定义8192个描述符

理论上,GDT可以位于内存的任何一个地方,但是很遗憾,目前只能在1MB内存以内

  • 必须在保护模式之前有GDT
  • 实模式只能访问1MB内存

当然,允许在保护模式以后给GDT换个位置

描述符

分类

  • 存储器的段描述符:描述一般的代码段和数据段(栈段就是数据段)
  • 系统描述符
    • 系统的段描述符
    • 门描述符:描述与程序有关的作用,如中断

111

Q:可能有人疑惑,怎么不把两边的位都展示出来

A:因为,S和Type决定一个描述符的种类,如果S和Type不一样,两边也是不一样的

当处理器拿到一个描述符的时候,先检查S位,根据s位再去检查Type

存储器的段描述符

段描述符格式

222

存储器的段描述符要求,S = 1,因而高双字的第12位为1

x = 0

在S位为1的情况下,高双字的11位是执行位x(execudtable)

若x = 0,表示不可执行,进而是数据段在这种情况下,另外三位分别是E、W、A位

333

E位

E表示数据段的扩展方向,(Expand),E = 表示向上扩展,则为普通的段,反之向下,那么就是栈段

W位

W表示是否可写(Writtable),为0表示不可写入,反之可写

x = 1

444

x = 1表示该段可执行,则该段为可执行段

C位

C表示是否属于特权级可依从,这就不得不涉及特权级了,高双字的13, 14位DPL(Descriptor Privilege Level)表示特权级,0, 1, 2, 3

C = 0表示非依从的代码段,反之表示为依从的代码段

非依从:只有特权级相同的程序才能直接跳转过来执行

依从:特权级低的程序可以直接跳转过来执行

如果没有特殊要求的话,这位通常是0

R位

代码段总是可以执行的,但是为了防止被破坏,所以是不能写入的,至于能否读出,取决于R位

如果R=1,表示可以读出,反之不可

Q:如果代码段不可读,那么处理器是怎么读该代码段呢,从中取指令执行呢?

A:事实上,这个不可读并非限制处理器取指令,执行指令,而是限制像访问数据段一样访问代码段

eg:使用mov指令读取段中的内容

A位

不论是数据段还是代码段,该位都为A(Accessed),已访问位,是否已访问,或者说是否使用过

每当访问该段的时候,该位有处理器或操作系统自动置1,可以在一定时间内检测该位的变动频率,进而知道该段的使用频率,若不常用且又需要内存,那么就可把该段放到磁盘上以实现虚拟内存技术

段界限和访问控制

在段描述符中,用20位来表示段的界限。

段的扩展方向
向下扩展的段
  • x = 1
  • x = 0且E = 0

通常向下的段都是用于栈段,向下的段都可以使用sp或者esp寄存器。此时段的即为FFFF或者FFFF_FFFF减去段的界限

描述符的G(粒度)

高双字的23位为G位,若G为0表示字节为单位,如果G位是1,则段界限为4KB为单位

若G= 1

则实际使用的段界限 = 描述符中的段界限* 0x1000 + 0xFFF

描述符的P位

位于高双字的15位,表示段是否存在的。P位是由处理器检查的。每当访问一个段时,检查到P位为0,则会产生中断。

描述符的L位

位于高双字的21位,表示64位的长模式,目前置0即可

描述符的D/B位

高双字的22位为D/B位,笼统的说,该为表示段是以16位还是32位操作。若为1则表示32位,反之则为16位

描述符的AVL位

位于高双字的20位,通常由操作系统来使用,是保留的。

GDT

处理器规定,第0个描述符必须为0,用以防止用户忘记初始化GDT,如果选择到了GDT的第0个描述符将会引发异常

A20地址线

一切都是历史遗留问题,在8086时代很多程序员依靠第20位进位为0工作,所以当出现第21根地址线时,进位并不会被丢弃

555

早期的策略就是使用与门,一个输入是A20地址线,另一个是8042键盘控制器接口,输出还是A20

8042

键盘控制器是可编程的,可以通过可控制8042的端口对8042进行编写程序,其中一个端口叫0x60端口,位1连接与门,若此位为1,那么与门的输出取决于A20地址线,反之若为0,则输出只会为0

改进后

666

从80486开始出现了A20M#引脚,意思是电平屏蔽(低电平有效)。

ICH芯片,输入输出控制芯片

在这个芯片有一个用于兼容老设备的端口0x92,位0用于连接处理器的INI#引脚 上,若此位从0变1,则处理器会复位,即重新启动

这个端口位1连接到一个或门上,当然为了兼容,这个或门还是连接到了老式键盘控制器上

in al, 0x92
or al, 0000_0010B
out 0x92, al

仅仅三行代码即可打开A20地址线

选择子

由于段寄存器是16位的,所以选择子也是16位的

位0位1处用于存储RPL,即请求特权级,关于特权级,后续会专门写一篇出来

位2TI位(Table INdicator),TI位为1表示在LDT中索引描述符,

位3~位15是描述符的索引值,可以看出,选择子的索引值部分13位,2^13 = 8192,因此最多可以索引8192个段,这个GDT是吻合的

控制寄存器CR0

在CR0的位0就是开启保护模式的开关

附上其他字段

777

mov eax, cr0
or eax, 0x1
mov cr0, eax

同样三行代码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值