lyl610abc 发表于 2021-4-13 00:34

保护模式笔记四 段描述符结构

本帖最后由 lyl610abc 于 2021-6-5 10:19 编辑

# 前言

所有保护模式索引链接:[保护模式笔记一 保护模式介绍](https://www.52pojie.cn/thread-1415096-1-1.html)

先前了解了段描述符和段选择子之间的对应关系,继续深入学习段描述符的结构

# 段描述符结构

!(https://610-pic-bed.oss-cn-shenzhen.aliyuncs.com/2.png)

| 数据位 | 31-24| 23   | 22         | 21      | 20               | 19-16      | 15   | 14-13    | 12         | 11-8   | 7-0    |
| ------ | ------ | ---- | ------------ | ------- | ---------------- | ---------- | ------ | -------- | ---------- | ------ | ------ |
| 含义   | Base   | G    | D/B          | 0       | AVL            | Seg.Limit| P      | DPL      | S          | Type   | Base   |
| 解释   | 基地址 | 粒度 | 默认操作大小 | 固定为0 | 用于系统软件使用 | 段大小限制 | 有效位 | 特权等级 | 描述符类型 | 段类型 | 基地址 |

------

| 数据位 | 31-16       | 15-0          |
| ------ | ----------- | ------------- |
| 含义   | Base Adress | Segment Limit |
| 解释   | 基地址      | 段大小限制    |

------

## 段描述符与段寄存器的对应关系

| 段寄存器组成   | Base                                 | Limit                           | Attribute                        |
| :--------------- | :----------------------------------- | :-------------------------------- | :------------------------------- |
| **数据宽度**   | 32位                                 | 32位                              | 16位                           |
| **描述**         | 基地址(当前段的起始地址)         | 大小限制(当前段的整个长度)      | 属性(当前段是否可读可写可执行) |
| **对应段描述符** | 段描述符中的3段base                  | 段描述符中的2段limit和G位共同决定 |                                  |
| **对应位**       | 高4字节:24~31 0~7 ,低4字节:16~31 | 高4字节:16~19,低4字节:0~15   | 高4字节:8~23                  |

## P位

当段描述符加载至段寄存器时,CPU首先要做的事就是检查段描述符的P位

|      | P==0               | P==1               |
| ---- | ------------------ | ------------------ |
| 含义 | 该段描述符**无效** | 该段描述符**有效** |

也就是说:**P位决定了该段描述符是否有效**

------

## G位

CPU判断完段描述符P位有效后,还需要判断地址是否超出Limit

但会发现这里的Limit分为了两段,但两段的总长度也只有4+16=20位,和段寄存器中的Limit的32位不匹配

这里的Limit的最大表示范围是:0~2的20次方-1=0~0xFFFFF

而段寄存器中的Limit的最大表示范围是:0~2的32次方-1=0~0xFFFFFFFF

很显然现在的Limit无法表示段寄存器中的Limit了,为了解决这个问题,引入了G位:粒度(用来表示Limit的单位)

|          | G==0            | G==1                           |
| -------- | ----------------- | -------------------------------- |
| 含义   | limit以字节为单位 | limit以4096=2的12次方 字节为单位 |
| 表示范围 | 0~0xFFFFF      | 0xFFF~0xFFFFFFFF                |

也就是说:**G位决定了limit的单位**

------

## S位

S位用来标记当前描述符的类型

|      | S==0         | S==1               |
| ---- | ------------ | -------------------- |
| 含义 | 系统段描述符 | 代码段或数据段描述符 |

段描述符可以分为**系统描述符、代码段描述符和数据段描述符**

根据S位的不同(描述符类型的不同)对应的Type域也不同

也就是说:**S位决定了Type域的含义**

------

## Type域

Type占据了第11位到第8位,共4位

------

### S位为1时

当S==1时,该段描述符为代码段描述符或者数据段描述符

!(https://610-pic-bed.oss-cn-shenzhen.aliyuncs.com/image-20210412223417579.png)

| 十进制 | 11   | 10                                  | 9               | 8               | 描述符类型   | 描述                                     |
| ------ | ---- | ----------------------------------- | --------------- | ----------------- | ------------ | ---------------------------------------- |
|      |      | **E(是否向下扩展)**               | **W(是否可写)** | **A(是否可访问)** |            |                                          |
| 0      | 0    | 0                                 | 0               | 0               | 数据段描述符 | 只读                                     |
| 1      | 0    | 0                                 | 0               | 1               | 数据段描述符 | 只读,可访问                           |
| 2      | 0    | 0                                 | 1               | 0               | 数据段描述符 | 可读可写                                 |
| 3      | 0    | 0                                 | 1               | 1               | 数据段描述符 | 可读可写可访问                           |
| 4      | 0    | 1                                 | 0               | 0               | 数据段描述符 | 只读,向下扩展                           |
| 5      | 0    | 1                                 | 0               | 1               | 数据段描述符 | 只读,向下扩展,可访问                   |
| 6      | 0    | 1                                 | 1               | 0               | 数据段描述符 | 可读可写,向下扩展                     |
| 7      | 0    | 1                                 | 1               | 1               | 数据段描述符 | 可读可写,向下扩展,可访问               |
|      |      | **C(是否可以从较低的特权级别调用)** | **R(是否可读)** | **A(是否可访问)** |            |                                          |
| 8      | 1    | 0                                 | 0               | 0               | 代码段描述符 | 只可执行                                 |
| 9      | 1    | 0                                 | 0               | 1               | 代码段描述符 | 只可执行,可访问                         |
| 10   | 1    | 0                                 | 1               | 0               | 代码段描述符 | 可执行可读                               |
| 11   | 1    | 0                                 | 1               | 1               | 代码段描述符 | 可执行可读,可访问                     |
| 12   | 1    | 1                                 | 0               | 0               | 代码段描述符 | 只可执行,可从较低特权级别调用         |
| 13   | 1    | 1                                 | 0               | 1               | 代码段描述符 | 只可执行,可从较低特权级别调用,可访问   |
| 14   | 1    | 1                                 | 1               | 0               | 代码段描述符 | 可执行可读,可从较低特权级别调用         |
| 15   | 1    | 1                                 | 1               | 1               | 代码段描述符 | 可执行可读,可从较低特权级别调用,可访问 |

------

主要说明一下**向下扩展和非向下扩展(向上扩展)**:

向上扩展就是:该段描述符所描述的**地址的有效范围**是从Base开始到Base+Limit结束

为下图中的红色部分:

!(https://610-pic-bed.oss-cn-shenzhen.aliyuncs.com/image-20210412232737696.png)

------

与之相反,向下扩展则是:该段描述符所描述的**地址的有效范围**是**除了** 从Base开始到Base+Limit结束 之外的部分

为下图中的红色部分

!(https://610-pic-bed.oss-cn-shenzhen.aliyuncs.com/image-20210412232754839.png)

------

### S位为0时

当S==0时,该段描述符为系统描述符

系统描述符有分为以下类型:

!(https://610-pic-bed.oss-cn-shenzhen.aliyuncs.com/image-20210412224835393.png)

------

| 十进制 | 11   | 10   | 9    | 8    | 描述                     |
| ------ | ---- | ---- | ---- | ---- | ------------------------ |
| 0      | 0    | 0    | 0    | 0    | 保留                     |
| 1      | 0    | 0    | 0    | 1    | 16位 任务状态段TSS(可用) |
| 2      | 0    | 0    | 1    | 0    | LDT                      |
| 3      | 0    | 0    | 1    | 1    | 16位 任务状态段TSS(繁忙) |
| 4      | 0    | 1    | 0    | 0    | 16位 调用门            |
| 5      | 0    | 1    | 0    | 1    | 任务门                   |
| 6      | 0    | 1    | 1    | 0    | 16位 中断门            |
| 7      | 0    | 1    | 1    | 1    | 16位 陷阱门            |
| 8      | 1    | 0    | 0    | 0    | 保留                     |
| 9      | 1    | 0    | 0    | 1    | 32位 任务状态段TSS(可用) |
| 10   | 1    | 0    | 1    | 0    | 保留                     |
| 11   | 1    | 0    | 1    | 1    | 32位 任务状态段TSS(繁忙) |
| 12   | 1    | 1    | 0    | 0    | 32位 调用门            |
| 13   | 1    | 1    | 0    | 1    | 保留                     |
| 14   | 1    | 1    | 1    | 0    | 32位 中断门            |
| 15   | 1    | 1    | 1    | 1    | 32位 陷阱门            |

关于系统描述符中的TSS、调用门、中断门、陷阱门 留作之后的笔记,这里不再展开

------

**Type域决定了当前段的属性**

------

## D/B位

D/B位分别作用于3种情况:

1. 对CS段的影响
2. 对SS段的影响(SS段也属于数据段)
3. 对向下扩展的数据段的影响

------

|                  | D/B == 0               | D/B == 1                  |
| ---------------- | ------------------------ | ------------------------- |
| CS段             | 采用16位寻址方式         | 采用32位寻址方式          |
| SS段             | 使用16位堆栈指针寄存器SP | 使用32位堆栈指针寄存器ESP |
| 向下扩展的数据段 | **段上限**为64KB         | **段上限**为4GB         |

------

主要说明一下对 向下扩展的数据段的影响

### D/B位为1时

!(https://610-pic-bed.oss-cn-shenzhen.aliyuncs.com/image-20210412232718593.png)

------

### D/B位为0时

!(https://610-pic-bed.oss-cn-shenzhen.aliyuncs.com/image-20210412232853145.png)

------

## DPL

DPL=Descriptor privilege level(描述符特权等级)为:访问这个描述符所需的特权级别(环ring)

关于段的权限检查,留作之后的笔记,这里不再展开

------

# 根据结构分析段描述符

大致了解了段描述符的结构后,就可以通过结构来分析一个段描述符了

给出的示例段描述符为:00cffb00`0000ffff

先转换成二进制:0000 0000 1100 1111 1111 1011 0000 0000 ` 0000 0000 0000 0000 1111 1111 1111 1111

按照对应的格式填入:

| 数据位 | 31-24    | 23   | 22         | 21      | 20               | 19-16      | 15   | 14-13    | 12         | 11-8   | 7-0      |
| ------ | -------- | ---- | ------------ | ------- | ---------------- | ---------- | ------ | -------- | ---------- | ------ | -------- |
| 含义   | Base   | G    | D/B          | 0       | AVL            | Seg.Limit| P      | DPL      | S          | Type   | Base   |
| 解释   | 基地址   | 粒度 | 默认操作大小 | 固定为0 | 用于系统软件使用 | 段大小限制 | 有效位 | 特权等级 | 描述符类型 | 段类型 | 基地址   |
| 数值   | 00000000 | 1    | 1            | 0       | 0                | 1111       | 1      | 11       | 1          | 1011   | 00000000 |

------

| 数据位 | 31-16            | 15-0             |
| ------ | ---------------- | ---------------- |
| 含义   | Base Adress      | Segment Limit    |
| 解释   | 基地址         | 段大小限制       |
| 数值   | 0000000000000000 | 1111111111111111 |

------

## P位

此时P位为1,表明当前的段描述符有效

------

## G位

此时的G位为1,表明此时limit以4096字节为单位

------

## Limit

此时的Limit为0xFFFFF,但其单位为4096字节,于是Limit等于0xFFFFF FFF 字节

------

## S位

此时的S位为1,表明该段描述符为代码段描述符或者数据段描述符

------

## Type域

此时的Type域为1011,表明该段描述符为代码段描述符,且可执行可读,可访问

------

## D/B位

此时的D/B位为1,表明此时采用32位寻址方式

------

## DPL

此时的DPL为11,表明访问这个描述符所需的特权级别为ring3(应用层)

------

# 说明

此篇笔记大体介绍了段描述符的结构,以及如何通过结构来解析一个段描述符的含义

目前还剩下段的权限检查和系统描述符没有具体说明,留作之后的笔记(* ̄( ̄ *)

minibeetuaman 发表于 2021-4-13 14:29

lyl610abc 发表于 2021-4-13 12:02
从0x7c00是什么意思

开机之后bios把mbr里面的代码加载到这个固定的物理地址开始执行,然后才是各种初始化以及实模式转保护模式

lyl610abc 发表于 2021-4-13 12:02

minibeetuaman 发表于 2021-4-13 09:13
类似读书笔记类的东西,建议把从0x7c00到转入保护模式这一阶段综合起来,不然新手看得云里雾里

从0x7c00是什么意思{:301_982:}

cdfox 发表于 2021-4-13 07:26

谢谢分享

江篱 发表于 2021-4-13 09:01

谢谢分享

sam喵喵 发表于 2021-4-13 09:01

这些标志位置是都得记住?

minibeetuaman 发表于 2021-4-13 09:13

类似读书笔记类的东西,建议把从0x7c00到转入保护模式这一阶段综合起来,不然新手看得云里雾里

Zoro. 发表于 2021-4-13 11:01

666666666666666666666666666666

lyl610abc 发表于 2021-4-13 12:01

sam喵喵 发表于 2021-4-13 09:01
这些标志位置是都得记住?

能记住自然最好,记不住的话就把每个标志位的含义记下就好{:301_971:}

辉哥j 发表于 2021-4-14 00:22

我去,大佬你真的勤快,我每天都看到你更新
页: [1] 2
查看完整版本: 保护模式笔记四 段描述符结构