概览

  • 基本工作模式
  • 线性地址
  • 寄存器扩展
  • 寻址扩展
  • 模式反转
  • 指令扩展
  • 全局描述符表、特权级、分页等

基本工作模式

Intel 32 位处理器架构简称 IA-32,尽管 8086 是 16 位的处理器,但它也是 32 位架构内的一部分。16 位到 32 位,不单单是地址线和数据线的扩展 ,实际上还有更多的部分,包括高速缓存、流水线、浮点处理部件、多处理器(核)管理、多媒体扩展、乱序执行、分支预测、虚拟化、温度和电源管理等。

80286 首次提出保护模式的概念。80286 的地址线扩充到 24 位,能够访问 16 MB的内存,但即使这样其仍然遵守内存分段模型,即使用 [段地址+偏址] 方式来访问内存,这是整个 IA-32 的基因 。在保护模式下,段寄存器中存放的不再是段地址,而是段选择子,段选择子映射到段描述符,段描述符中记录了段基址和段界限以及各种权限 同时,访问内存也不再需要将段地址向左移动四位,而是直接将段地址和偏移地址相加 。这样一来,段地址就无须位于 16 字节对齐的地方,而可以在 16 MB内存的任何角落。然而,80286 的偏移地址仍被限制在 64KB ,对段长度的限制阻碍了 80286 的应用,这是其最大的败笔。

虽然段地址可以不在 16 字节对齐的地方,但对齐有利于提高 CPU 寻址的效率。实际操作时,仍然会对齐。

80386 是划时代的,它的地址线和寄存器扩充到了 32 位,能够访问 4GB 的内存,其偏移地址也能达到 4GB!但如前文所说,分段是 IA-32 的基因,80386 也使用 [段地址+偏址] 方式来访问内存 。在 32 位模式下,处理器要求在加载程序时,先定义该程序所拥有的段(段描述符),然后才允许使用这些段。定义段时,除了基地址外,还附加了段界限、特权级别、类型等属性,当程序访问一个段时,处理器将用固件实施各种检查工作,以防止对内存的违规访问。80386 及其后续的 32 位处理器都兼容实模式,而且在刚加电启动时,这些处理器都位于实模式下,只有经过一番设置后才会进入保护模式

需要强调的是,实模式并不是说 32 位的 CPU 退化成了 16 位的 CPU,即使是在实模式下,其也能够使用 32 位 CPU 的资源 。也就是说,32 位 CPU 在 16 位实模式下,其本质仍然是 32 位 CPU,仍具备操作 32 位寄存器和 32 位操作数的能力!另外,不存在 32 位实模式(只能说32位 CPU 下的实模式)。

可以这么说:实模式一般指 8086 工作模式,而 32 位 CPU 的实模式是 8086 工作模式的扩展。

线性地址

IA-32 支持多任务,在多任务环境下,操作系统会给每个任务分配内存空间。在分段模型下,内存的分配是不定长的,程序大时,就分配一大块内存;程序小时,就分配一小块。时间长了,内存空间就会碎片化,就有可能出现一种情况:内存空间是有的,但都是小块,无法分配给某个任务。为了解决这个问题,IA-32 处理器支持分页功能, 分页功能将物理内存空间划分成逻辑上的页。页的大小是固定的,一般为 4KB,通过使用页,可以 简化内存管理 。当页功能开启时,段部件产生的地址就不再是物理地址了,而是线性地址(Linear Address),线性地址还要经页部件转换后,才是物理地址。

段的管理是由处理器的段部件负责进行的,段部件将段地址和偏移地址相加,得到访问内存的地址。不开启分页时,段部件产生的地址就是物理地址当页功能开启时,段部件产生的地址就不再是物理地址了,而是线性地址(Linear Address),线性地址还要经页部件转换后,才是物理地址

注意,线性地址是用来描述任务的地址空间的一种概念 ,IA-32 处理器上的每个任务都拥有 4GB 的虚拟内存空间 ,这是一段长 4GB 的平坦空间(平坦模型),就像一段平直的线段,因此叫线性地址空间。详细内容将在后续博客中讨论。

平坦模型一定在分页机制下运行,分页机制是内存平坦模型的基础

寄存器扩展

  1. 16 位下的 8 个通用寄存器被扩展到 32 位:eax,ebx,ecx,edx,esp,ebp,edi,esi;就如前文所说,即使在实模式下也可以使用这些 32 位寄存器。注意:1)指令的源操作数和目的操作数必须有相同的长度;2)32 位通用寄存器的高 16 位不可独立使用 ,低 16 位保持对 16 位处理器的兼容。
  2. 标志寄存器 FLAGS 由 16 位扩展到 32 位 EFLAGS,低 16 位与之前保持一致,见汇编入门一文;高 16 位将在后续文章阐述。
  3. 段寄存器仍为 16 位,但其中不再存放段基址,而是存放 16 位的段选择子。增添了两个新段寄存器:FS,GS
  4. 每个段寄存器都包含一个 64 位的不可见部分,称为描述符高速缓存寄存器 ,其中装着被整理后的段描述符。引入该寄存器的原因是:1)段描述符在内存中,获取较慢;2)段描述符中,段基址被分成 3 部分,段界限被分成两部分,CPU 无法直接使用,需要整理放入寄存器后才能供CPU使用。

寻址扩展

实模式的内存寻址方式:

32 位 CPU 的寻址方式:

可见,32 位保护模式允许所有通用寄存器作为 基址寄存器 ,除 ESP 之外的所有通用寄存器也可以作为 变址寄存器 ,同时变址寄存器还能够乘上固定的比例因子。注意,实模式下不能使用 SP 作为基址寄存器,而 32 位保护模式下可以使用 ESP 作为基址寄存器

模式反转

IA-32 的指令格式:

前缀 操作码 寻址方式和操作类型 立即数 偏移量

以上格式起源于 16 位处理器,32 位处理器在此基础上扩展了数据的宽度,其他基本保持不变。虽然 32 位采用的是和 16 位相同的指令格式,但寻址方式和寄存器的定义却是另起炉灶的 。考虑如下机器代码:

1
8B 50 02

其对应的 16 位指令为:

1
mov dx,[bx+si+0x02]

其对应的 32 位指令位:

1
mov edx,[eax+0x02]

所以说,相同的机器代码在两种模式下可能对应着不同的指令 。而我们在前文中已经反复强调,在32位 CPU 的实模式中仍然可以使用 32 位寄存器,那么问题来了,对于机器代码 8B 50 02 ,CPU 怎么知道将它翻译成 16 位指令还是 32 位指令呢?为解决此问题,编写程序时必须使用 bits 关键字指定运行环境:

1
2
3
4
5
#有无[]都可
bits 16
[bits 16]
bits 32
[bits 32]

如果不指定,则默认为 [bits 16] 。指定环境后,如果某条指令在 A 模式下使用了 B 模式下的寄存器,则该指令的机器码就会加上前缀 0x66 ,来临时反转当前模式。比如在 16 位模式下,inc ax 的机器码为:0x40 ,而 inc eax 的指令则为 66 40 。因此,前缀 0x66 具有临时反转当前模式的作用

值得一提的是,对于 mov 段寄存器,通用寄存器 这样的指令,在 16 位和 32 位模式下的机器码完全相同。如下:

1
2
3
4
[bits 16]
mov ds,ax
[bits 32]
mov ds,ax

这两条指令的机器码都为 8E D8 。为什么这样设计?因为有前缀会使处理器多花一个时钟来处理,而这样的指令很频繁,而且牵涉到内存段的访问,所以也很重要,因此它们被设计得相同。

指令扩展

  • 对于 shl,shr 指令,在实模式下使用 cl 寄存器存储移动的位数,在 32 位保护模式下同样如此。

  • mul bx ,实模式下,另一个乘数在 ax 中,积的高位放在 dx 中,低位放在 ax 中。在 32 位下,积直接放在 eax 中
    mul ebx ,另一个乘数放在 eax 中,积的高位放在 edx,低位放在 eax 中。
    div bx ,实模式下,被除数高位在 dx 中,低位在 ax 中,商存放在 ax,余数放在 dx 中。32 位下相同
    div ebx ,被除数高位放在 edx,低位放在 eax,商放在 eax,余数放在 edx。

  • 对于 push 指令:

    • 立即数:
      无论是实模式还是保护模式,压入 16 位,则栈指针减 2;压入 32 位,则栈指针减 4 。压入 8 位数据则按当前模式默认大小压入 ,见下。

      1
      2
      3
      4
      #实模式下:
      push byte 0x1 #sp-=2
      push word 0x1 #sp-=2
      push dword 0x1 #sp-=4
      1
      2
      3
      4
      #保护模式下:
      push byte 0x1 #esp-=4
      push word 0x1 #esp-=2
      push dword 0x1 #esp-=4
    • 段寄存器:
      按当前模式的默认操作数大小压入:

      1
      2
      3
      4
      #实模式下:
      push es #sp-=2
      #保护模式下:
      push es #sp-=4
    • 通用寄存器和内存:

      无论在保护模式还是实模式,如果压入 16 位,则栈指针减 2;如果压入 32 位,则栈指针减 4;

保护模式的其他特性如全局描述符表、特权级、分页等内容较多,也是保护模式的精髓,后续将单独记录。

文章参考:《操作系统真相还原》《x86实模式到保护模式》分段、分页和平坦模型