文章目录
- 前言
- 一、寄存器变化
- 二、寻址变化
- 三、为什么段寄存器依然是16位?
查看系列文章点这里: 操作系统真象还原
前言
我们在前面已经介绍过实模式了,它是32位 CPU 的一种工作模式,模拟了16位 CPU 的工作环境,但是大多数时候 CPU 并不会处于实模式,而是保护模式,我们接下来看看实模式和保护模式有什么区别。
一、寄存器变化
从实模式转换到保护模式之后,寄存器从本质上来说并没有任何变化,因为两种模式都属于一个 CPU,变化的只不过是这些寄存器的使用方法。
首先第一个变换的就是寄存器的位数,在实模式下,大多数寄存器有8位或者16位,而在保护模式中,寄存器可以达到32位,若想使用32位的寄存器,只需要在原先16位寄存器名称前加一个大小字母“E”就可以了。值得强调的是,段寄存器即便在保护模式下也依然只有16位。其它寄存器可以见下图:
32位 | 16位 | 8位 |
---|---|---|
EAX | AX | AH、AL |
EBX | BX | BH、BL |
ECX | CX | CH、CL |
EDX | DX | DH、DL |
ESI | SI | |
EDI | DI | |
EBP | BP | |
ESP | SP | |
EFLAGS | FLAGS | |
EIP | IP | |
CS | ||
DS | ||
ES | ||
FS | ||
GS | ||
SS |
段寄存器之所以还是只有16位,是因为16位已经够用了,没有必要扩展到32位,毕竟资源能省就省,这是硬件设计的原则。
变化的只是寄存器的位数,含义用法确都没有变,不清楚的可以看看x86 CPU的实模式——寄存器(一)。
除了寄存器位数发生了变化,保护模式下也多出来了很多新的寄存器的,例如DCR寄存器、GDTR寄存器等等,但是由于直接讲不好理解其作用,故在用到这些寄存器的时候再说叭。
二、寻址变化
我们在前面详细讲过实模式下的寻址方式,不清楚的可以看看x86 CPU的实模式——寻址(二),实模式下的寻址方式对寄存器的使用有严格的限制,这一点大大限制了编程的灵活性,于是在保护模式中改进了这一点,保护模式下几乎所有的寄存器都可以做基址寄存器和变址寄存器。
除此之外,保护模式还支持对变址寄存器乘上一个比例因子(只能是1、2、4、8),具体对比可以见下图:
如果还是难以理解,可以看看下面的例子:
;实模式
mov ax,[si]
mov ax,[di]
mov ax,[bx]
mov ax,[bx+si]
mov ax,[bx+si+0x1234]
mov ax,[bx+di]
mov ax,[bx+di+0x1234]
;保护模式
mov eax,[eax+edx*8+0x12345678]
mov eax,[eax+edx*2+0x8]
mov eax,[ecx*4+0x1234]
mov eax,[esp]
mov eax,[esp+2]
三、为什么段寄存器依然是16位?
我们知道IA32架构下,寻址方式都是基于“ 段基址:偏移地址方式 ”。在实模式下,是“ 段基址寄存器*16+段偏移地址 ”,并且乘16是因为,地址线是20位,而寄存器只有16位,为了正确表示地址才这么做的。
那么在保护模式下,理论上只要寄存器和地址线都是32位,就可以实现寻址的功能。那么为什么实际上保护模式下,段寄存器还是16位呢?
简单来说就是出于安全考虑(最主要的原因),实模式下操作系统和用户程序都可以肆意访问内存,让用户程序随意操控内存,这种行为是非常不安全的。因此,为了增加安全性,为了区分操作系统和用户程序,必须要改变一下访问内存的方式。插一嘴,这也是实模式和保护模式名字的由来。
所以,保护模式就不能简单的将寄存器和地址线变成32位就OK了。要想解决安全问题,就要对用户程序做出限制,那就需要存储额外的信息。又由于寄存器只有32位,已经没有地方存放这些信息了,所以干脆就将段基址和这些信息全部放到内存中算了。
既然都被放到内存中了,那就需要告诉 CPU 这些信息被放到内存中的那个地方了,如何告诉?就是通过段寄存器,它存储了一个叫“ 选择子 ”的结构,通过它和GDTR寄存器的值,就可以确定这些信息在内存中的位置了。
现在知道为什么段寄存器还是16位的了叭,下一篇文章会详细讲解一下CPU如何通过“ 选择子 ”来寻址的。
持续更新中~~