最初开始ORANGE‘S的时候便是卡在了保护模式,感觉代码枯燥难懂,文字读了几遍,还是一片迷茫,想到自己基础太渣,于是看了大灰狼,保护模式终于有了一个基本的概念。因此笔记基本还是用的大灰狼的课程笔记,不过代码和实现环境是用的ORANGE‘S的了,最终的目的还是学习ORANGE’S。可惜大灰狼老师的第二部分一直没有找到,后面的学习进度自己也有些担心。
了解保护模式首先从实模式开始。
一、实模式
首先,计算机加点后,CPU默认运行于实模式下。
实模式有如下几个特点:只能访问地址在1M以下的内存(1M以下的内存为常规内存,而1M以上的内存为扩展内存)‘
寻址方式为seg:offset,基地址:偏移地址模式,能够读取20位的也就是1M的内存。
但80386有32根地址线,也就是2的32次方即4GB的寻址空间,然而又完全兼容16位CPU,也就是可以继续用16位CPU的内存寻址方式。也就是说,在80386中,仍然使用16位的寄存器来表示内存的地址,但是寻址方式会不同与实模式的基地址:偏移地址模式,这个问题,就是保护模式需要解决的问题。
二、保护模式
保护模式下仍然使用16位的段寄存器和通用寄存器
1,内存访问思路
实模式与保护模式下内存都被分为一个个内存段来表示。而实模式下,使用基地址:偏移地址的方式来进行数据的访问。在保护模式下,则将事先分好的内存段的信息存入一个表格中,而段寄存器则保存所访问的内存段在这个表格中的索引。于是,在保护模式下,段寄存器的内容有了新的意义,也就是用于保存这张表的某个索引项。而这张表示内存分段信息的表格就是段描述符表,而表中每一个表示32位内存段的信息则叫做段描述符,而保存表中索引的段寄存器也就叫做段选择子。
2,段选择子
段选择子也就是段寄存器中的内容,共有16位,其中高13位用于表示段描述符中的索引,低3位用于表示段描述符表中所指向的段描述符属性。
从段选择子的布局可以看出,段描述符最多有2的13次方也就是8096个,也就是最多有8096个描述符。
低位的第三位TI是table indicator,用于表示是从全局描述符表中读取描述符还是从局部描述符中读取描述符。
局部描述符:程序自己内部的数据(如堆栈段,数据段信息)
全局描述符:程序需调用的外部数据(如库函数等)
最低两位(RPL):request priviledged level,用于特权检查
3,形成物理地址
4,段描述符
段描述符有8个字节。
段界限(segment limit):共20位,分2个部分保存,第一部分保存在1,2字节中,剩余在第7字节的低四位。
段基地址(segment base):共32位,分两个部分保存,第一部分0-23位,存放在3-5字节中,第二部分24-31位存放在第8字节中。
段属性(attributes):包含段属性和段界限的第二部分。其作用是描述该段是数据段,代码段还是堆栈段;以及段描述符所指定的内存段在物理内存中是否存在。
若是数据段/堆栈段,是否可读可写。
若是代码段,是否可执行。
其中段属性的16位的具体分布如下:
type:说明存储段描述符所描述的存储段的具体属性(数据/代码,读/写)
DT:说明了该描述符所指定的是系统段还是存储段(一般为存储段)
DPL:特权级别,最高为0,最低为3(操作系统的级别为0)
P:该描述符对地址的转换是否有效(1:有效 0:无效)
limit:段界限的剩余部分
AVL:软件可利用性,80386对该位未做规定
D:若为代码段,是16位(0)还是32位(1);若为数据段,是64k(0)还是4GB(1)
G:段界限粒度,G=0,段边界为64k,G=1,段边界为4GB(保护模式下都为4GB)