【X86汇编语言 从实模式到保护模式】06 32位 x86 处理器编程架构

本文详细介绍了IA-32架构的基本执行环境,包括寄存器扩展、工作模式和线性地址的概念。同时,探讨了现代处理器的结构和特点,如流水线技术、高速缓存、乱序执行、寄存器重命名以及分支目标预测,展示了如何通过这些技术提升处理器的性能和效率。
摘要由CSDN通过智能技术生成

1. IA-32 架构得基本执行环境

1.1 寄存器扩展

8 个通用寄存器 AX,BX,CX,DX,SI,DI,SP,BP 从 16 位扩展成了 32 位,分别密码位 EAX,EBX,ECX,EDX,ESI,EDI,ESP,EBP。如下图所示。
在这里插入图片描述
在 32 位模式下,指针寄存器 IP 扩展成了 32 位的 EIP 用来访问 4GB 的内容。标志寄存器 FLAGS 也被扩展成了 32 位的 EFLAGS。如下图所示。
在这里插入图片描述
在 32 位模式下,段寄存器 CS,DS,ES 等保存的不再是 16 位的段基址,而是段选择子。即用于选择所要访问的段,因此它们的名字严格来讲是段选择器。,除段选择器之外,每个段寄存器还包括一个不可见部分,描述符高速缓存器,里面有段的基地址和各种访问属性。这部分内容无法访问,由处理器自读使用,如下图所示。
在这里插入图片描述

1.2 基本的工作模式

在 32 位保护模式下,可以访问 4GB 的内存,最典型的情况下,可以将 4GB 内存定义成一个段来处理,即平坦模式。

1.3 线性地址

在 IA-32 处理器中编程,,访问内存时,需要在程序中给出段地址和偏移量。

段的管理由段部件负责进行,段部件将短地址和偏移地址相加,一般来说,段部件产生的地址就是物理地址。在分段模式下,内存的分配是不定长的,会产生碎片化内存空间。因此 IA-32 处理器支持分页功能,分页功能将物理内存空间划分成逻辑上的页。页的大小是固定的,一般是 4KB。如下图所示,页功能开启时,段部件产生的地址不再是物理地址而是线性地址,线性地址还要经过页部件转换后才是物理地址。
在这里插入图片描述
线性地址用来描述任务的地址空间,如上图,IA-32 处理器上的每个任务都有 4GB 的虚拟内存空间,这是一段 4GB 的平坦空间,也叫线性地址空间,段部件产生的地址对于着线性地址空间上的每一点。

2. 现代处理器的结构和特点

2.1 流水线

处理器可以做很多事情,能够执行各种不同的指令,完成不同的功能,但这些事情大多不会再一个时钟周期内完成。执行一条指令,需要从内存中取指令,译码,访问操作数和结果,并进行移位、加法、减法、乘法以及其他任何操作。

为了提高处理器的执行效率和速度,可以把一条指令的执行过程分解成若干个细小的步骤并分配给相应的单元来完成。各个单元的执行都是独立的、并行的。如此一来,各个步骤在时间上就会重叠起来,这种执行指令的方法,就是**流水线(Pipe-Line)**技术。

比如,一条指令的执行过程分为取指令、译码和执行三个步骤的话。并且每个步骤都要花一个时钟周期,那么如下图所示,如果采用顺序执行,则执行三条指令就要花 9 个时钟周期,每 3 个时钟周期才能得到一条指令的执行结果;如果采用 3 级流水线技术的话,则执行这三条指令只需要 5 个时钟周期,每隔一个时钟周期就能够得到一条指令的执行结果。
在这里插入图片描述

2.2 高速缓存

高速缓存是处理器于内存(DRAM)之间一个静态存储器,容量较小,但是速度可以和处理器匹配。高速缓存的用处源于程序在运行时所具有的局部性规律。程序往往是序列化地从内存中取指令执行地。访问数据时,要访问地数据通常都被安排在一起,利用该原理,可以将处理器正在访问和即将访问地指令和数据从内存调入高速缓存中。

2.3 乱序执行

为了实现流水线技术,需要将指令拆分成更小的可独立执行部分,即拆分成微操作(micro-operation)。一旦将指令拆分成微操作,处理器就可以在必要地时候乱序执行(Out-Of-Order Execution)程序。考虑以下例子:

mov   eax , [mem1]
shl   eax , 5
add   eax , [mem2]
mov   [mem3] , eax

这里 add eax , [mem2] 可以拆分成两个微操作。先从 mem2 对应的地址取数据,然后将数据与eax寄存器中存的数据相加,得到的结果存入eax寄存器。如此一来,在执行逻辑左移指令的同时,处理器可以提前从内存中读取 mem2 的内容。典型的,如果数据不在高速缓存中,那么处理器在获取 mem1 的内容后,会立即开始获取 mem2 的内容,与次同时,shl 指令的执行早就开始了。

2.4 寄存器重命名

考虑以下例子:

mov eax,[meme1]
shl eax,3
mov [mem2],eax
mov eax,[meme3]
add eax,2
mov [mem4],eax

以上代码片段做了两件事,但是互不相干:

  • 将 mem1 里的内容左移 3 次()乘以 8,传给 mem2。
  • 将 mem3 的内容加上 2 传给 mem4。

如果为我们给最后三条指令使用不同的寄存器,那么将更明显看出这两件事的无关性。事实上,处理器实际上也是这样的。处理器为最后三条指令使用了另一个不同的临时寄存器,因此,左移和加法可以并行处理。

IA-32 架构的处理器只有 8 个 32 位通用寄存器,但通常都会被使用(甚至可能不够)。对于这种情况,处理器内部有大量的临时寄存器可用,处理器可以重命名这些寄存器以代表一个逻辑寄存器,比如 EAX。

寄存器重命名以一种完全自动和非常简单的方式工作。每当指令写逻辑寄存器时,处理器就会位那个逻辑寄存器分配一个新的临时寄存器。

在所有操作完成后,那个代表 EAX 寄存器最终结果的临时寄存器的内容被写入真实的 EAX 寄存器,该处理过程称为引退(Retirement)

所有通用寄存器,栈指针、标志寄存器、浮点寄存器、甚至段寄存都有可能被重命名。

2.5 分支目标预测

流水线并不是百分之百完美的解决方案。实际上,有很多潜在的因素会使得流水线不能达到最佳的效率。一个典型的情况是,如果遇到一条转移指令,则后面那些已经进入流水线的指令就都无效了。换句话说,我们必须清空(Flush)流水线,从要转移到的目标位置处重新取指令放入到流水线。

随着复杂架构下的流水线变得越来越长,程序分支带来的问题变得很大。为了解决这个问题,引入了分支预测技术(Branch Prediction)

从统计学的角度来看,有些事情一旦出现,下一次出现的概率较大,一个典型的例子就是循环,比如下面的例子。

	xor  si , si
lops:
	......
	cmp  si , 20
	jnz  lops

当 jnz 指令第一次执行时,转移一定会发生。那么处理器就可以预测,下一次它还会转移到标号 lops 处,而不是顺序往下执行。事实上,这个预测通常是很准的。

在处理器内部,有一个小容量的高速缓存器,叫做分支目标缓存器(Branch Target Buffer,BTB)。当处理器执行了一条分支语句后,它会在 BTB 中记录当前指令的地址、分支目标的地址。以及本次分支预测的结果。下一次,在那条转移指令实际执行之前,处理器会查找 BTB ,看有没有最近的转移记录。如果能找到最近的条目,则推测执行和上次相同的分支,把该分支的指令送入流水线。

当该指令执行时,如果预测是失败的,那么清空流水线,同时刷新BTB中的记录。这个代价很大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值