从实模式到保护模式

intel 8086 来说。是一个16位的处理器。他有16位的寄存器。16位的数据总线。20位的地址线。寻址能力1M。因为是16位的寄存器。只有通过 seg:offset的方式。才能寻址1m的地址空间。
到了80386后的处理器。就变成了32位的处理器。寄存器是32位。数据总线也是32.地址也是32位。如果一个寄存器存放的是地址的话。直接寻址能力是4GB。但还是使用了 seg :offset的方式。

在32位的处理器中。仍是采用的是:段+偏移 的寻址方式。但这里的段和实模式下的段有本质的不同。在实模式下,“段”是物理地址的一部分,可以说是段的首地址。但在保护模式下的段。段值只是一个索引。(段值是放在cs ds 等 16位的寄存器中。)他指向一个数据结构的一个表项。在表项中详细定义了段的起始地址。段限长。段的属性的内容。这个数据结构就是 GDT ,LDT 。

GDT的表项有一个固定的名字叫 段描述符。段描述符的格式如下:(共8字节 32位的索引)
                                    |  byte7                     |  byte6|  byte5    |  byte4   |  byte3   |  byte2          |     byte1  |    byte0
                                    段基址(31..24)  |段  属  性             |段基址(23.....0)                     | 段限(0....15)

地址是32位的,所以段基址是四个字节。段的长度是1M。占两个字节。段属性占2个字节(包括段限长的高4位)。

段的属性是:

7     6        5      4             3      2       1     0           7         6       5       4          3      2      1        0 
G   D/B     0     avl            |段限长(19..16)|          p         |  DPl |       s          |t    y   p    e        |
 
描述GDT的表项的数据结构是 段选择子。段选择子的构成如下:
7     6        5      4             3      2       1     0           7         6       5       4          3      2      1        0 
 
                                   段        描       述     符     的      索    引                                         TI       RPL

如果ti和rpl都是0.那么索引就是段描述符相对于段表的偏移长度。

例子如下:

mov   ax,  DESC_VIDIO
mov   gs.,ax
mov   [gs:edi]  ,8                  ///[]表明从内存中去数据


第二步:

我们考虑下寻址的具体过程:
如果我们要到内存中取数据。那么 我们得到一个地址 是seg + offset的形式。
cpu的执行过程:
1. cpu通过 ldtr 寄存器知道GDT的具体地址
2. 通过seg 去找段表的该段的描述符表项。找到段的基址
3.然后用段基址+offset 就可以得到数据在内存中 的物理地址。 接下来就是取数据了 。

所以下一步的工作是 把gdt的基址和属性用 lgdt 加载到gdtr寄存器。(因为 段表是在内存中的。而段表的基址存在cpu中。)

gdtr的结构是:

 32位 的基址      16位的段界限

然后就是 开 A 20 的地址线。(向下兼容)   置 cr0寄存器的pe 位

最后就是一个 jmp 。进入保护模式 。
注意 :jmp 是一个从16位进入  32位 所以 用到 了
jmp dword  地址

就进入保护模式了

总结下;

准备 GDT
加载 GDT
开 A20
置 CR0
跳转 jmp


我们就进入了
原文地址:https://www.cnblogs.com/herso/p/1418997.html