x86汇编语言-从实模式到保护模式笔记

32位处理器的结构和特点

Posted by BINBIN Blog on October 24, 2019

IA-32 架构的基本执行环境

寄存器的扩展

在 16 位处理器内,有 8 个通用寄存器 AX、 BX、 CX、 DX、 SI、 DI、 BP 和 SP,其中,前 4 个还可以拆分成两个独立的 8 位寄存器来用,即 AH、 AL、 BH、 BL、 CH、 CL、 DH 和 DL。如图 10-1 所示, 32 位处理器在 16 位处理器的基础上,扩展了这 8 个通用寄存器的长度。

为了在汇编语言程序中使用经过扩展(Extend)的寄存器,需要给它们命名,它们的名字分别是 EAX、 EBX、 ECX、 EDX、 ESI、 EDI、 ESP 和 EBP。可以在程序中使用这些寄存器,即使是在实模式下:


mov eax,0xf0000005
mov ecx,eax
add edx,ecx

就像以上指令所示的那样,指令的源操作数和目的操作数必须具有相同的长度,个别特 殊用途的指令除外。因此,像这样的搭配是不允许的,在程序编译时,编译器会报告错误:

mov eax,cx ;错误的汇编语言指令

在本书中, 32 位模式特指 32 位保护模式。在这种模式下,可以完全、充分地发挥处理器的性能。同时,在这种模式下,处理器可以使用它全部的 32根地址线,能够访问 4GB 内存!

如图 10-2 所示,在 32 位模式下,为了生成 32 位物理地址,处理器需要使用 32 位的指令指针寄存器。为此, 32 位处理器扩展了 IP,使之达到 32 位,即 EIP。当它工作在 16 位模式下时,依然使用 16 位的 IP;工作在 32 位模式下时,使用的是全部的 32 位 EIP。和往常一样,即使是在 32 位模式下, EIP 寄存器也只由处理器内部使用,程序中是无法直接访问的。对 IP 和 EIP 的修改通常是用某些指令隐式进行的,这此指令包括 JMP、 CALL、 RET 和 IRET 等等。

32 位处理器增加了两个额外的段寄存器 FS 和 GS!

基本的工作模式

32 位模式特指 IA-32 处理器上的 32 位保护模式。不存在所谓的 32 位实模式, 实模式的概念实质上就是 8086 模式。

线性地址

为 IA-32 处理器编程,访问内存时,需要在程序中给出段地址和偏移量,因为分段是 IA-32架构的基本特征之一。传统上,段地址和偏移地址称为逻辑地址,偏移地址叫做有效地址(Effective Address, EA),在指令中给出有效地址的方式叫做寻址方式(Addressing Mode)。

inc word [bx+si+0x06]

在这里,指令中使用的是基址加变址的方式来寻找最终的操作数。

为了解决这个内存碎片化的问题, IA-32 处理器支持分页功能,分页功能将物理内存空间划分成逻辑上的页。页的大小是固定的,一般为 4KB,通过使用页,可以简化内存管理!

如图 10-3 所示,当页功能开启时,段部件产生的地址就不再是物理地址了,而是线性地址(Linear Address),线性地址还要经页部件转换后,才是物理地址。

线性地址的概念用来描述任务的地址空间。如图 10-3 所示, IA-32 处理器上的每个任务都拥有4GB 的虚拟内存空间,这是一段长 4GB 的平坦空间,就像一段平直的线段,因此叫线性地址空间。 相应地,由段部件产生的地址,就对应着线性地址空间上的每一个点,这就是线性地址。

流水线基本原理

高速缓存

寄存器的速度是最快的,原因在于它使用了触发器,这是一种利用反馈原理制作的存储电路。触发器的工作速度是纳秒(ns)级别的,当然也可以用来做为内存的基本单元,即静态存储器(SRAM),成本很高!

因为需要等待内存和硬盘这样的慢速设备,处理器便无法全速运行。为了缓解 这一矛盾,高速缓存(Cache)技术应运而生。高速缓存是处理器与内存(DRAM)之间的一个静态存储器,容量较小,但速度可以与处理器匹配!

乱序执行

为了实现流水线技术 ,需要将指令拆分成更小的可独立执行部分 ,即拆 分成微操作 (Micro-Operations),简写为μ ops。 比如:

add eax,[mem]

可以拆分成两个微操作,一个用于从内存中读取数据并保存到临时寄存器,另一个用于将 EAX存器和临时寄存器中的数值相加。

寄存器重命名

IA-32 架构的处理器只有 8 个 32 位通用寄存器,但通常都会被我们全部派上用场(甚至还觉得不够)。因此,我们不能奢望在每个计算当中都使用新的寄存器。不过,在处理器内部,却有大量的临时寄存器可用,处理器可以重命名这些寄存器以代表一个逻辑寄存器,比如 EAX。 寄存器重命名以一种完全自动和非常简单的方式工作。每当指令写逻辑寄存器时,处理器就为那个逻辑寄存器分配一个新的临时寄存器。再来看一个例子:

mov eax,[mem1]
mov ebx,[mem2]
add ebx,eax
shl eax,3
mov [mem3],eax
mov [mem4],ebx

假定现在 mem1 的内容在高速缓存里,可以立即取得,但 mem2 的内容不在高速缓存中。这意味着,左移操作可以在加法之前开始(使用临时寄存器代替 EAX)。为左移的结果使用一个新的临时寄存器,其好处是 EAX 寄存器中仍然是以前的内容,它将一直保持这个值,直到 EBX 寄存器中的内容就绪,然后同它一起做加法运算。如果没有寄存器重命名机制,左移操作将不得不等待从内存中读取 mem2 的内容到 EBX 寄存器以及加法操作完成。 在所有的操作都完成之后,那个代表 EAX 寄存器最终结果的临时寄存器的内容被写入真实的EAX 寄存器,该处理过程称为引退(Retirement)。 所有通用寄存器, 堆栈指针、标志、浮点寄存器,甚至段寄存器都有可能被重命名。

分支预测

这个属于CPU 流水线的设计范畴!

32 位模式的指令系统

详细请看书上,不作详细记录!