本文由zengl.com站长对
http://pan.baidu.com/share/link?shareid=3717576860&uk=940392313 汇编教程英文版相应章节进行翻译得来。
另外再附加一个英特尔英文手册的共享链接地址:
http://pan.baidu.com/share/link?shareid=2345340326&uk=940392313 (在某些例子中会用到)
下面继续上一节的内容:
Out-of-order execution engine (无序执行引擎):
无序执行引擎可以将前面指令预取操作传递过来的无序的指令流给缓存起来,为它们分配逻辑寄存器,最后通过微操作调度将微操作交给Retirement unit(指令退休毕业单元),由该单元将微操作交给execution unit(执行单元),并将执行的结果缓存起来,最后再将结果重组,从而让无序指令执行起来就像顺序执行指令效果一样。实现这套功能需要很复杂的电路设计。这套功能的实现,就可以让处理器不用像旧的有序执行引擎那样,每次都要等待指令的内存数据准备好才执行,可以先准备好的先执行,最后再将结果重组即可。奔腾4处理器的无序执行引擎最多可以同一时间处理126条指令,无序执行引擎的示意图如下:
图1-1
从图中可以看出来,Out-of-Order(无序执行引擎)由三个部分组成:
-
The allocator 指令缓冲空间分配器
-
Register renaming 指令中相关寄存器重命名
-
The micro-operation scheduler 微操作调度
指令缓冲空间分配器为正在执行的指令分配合适的缓冲空间,如果某条指令的相关资源不可用,分配器就停止对该指令的分配工作,转去为其他的指令分配空间。
Register renaming(寄存器重命名)部分负责为需要访问寄存器的指令分配合适的逻辑寄存器,下面会提到IA-32处理器中只有8个通用寄存器,Register renaming单元里包含有128个逻辑寄存器,当多条指令要同时访问同一个通用寄存器时,就可以由Register renaming通过寄存器分配表即图中的RAT将需要访问的寄存器映射到逻辑寄存器中,这样就可以加快处理那些需要访问同一寄存器集的指令。
微操作调度通过检测输入元素来判断微操作是否准备好,然后将准备好的微操作发送给Retirement unit(指令毕业单元),微操作调度使用两个队列来存放微操作,一个队列存放需要内存访问的微操作,另一个存放不需要内存访问的微操作。这些队列被绑定到dispatch ports(发送端口)上,通过发送端口将微操作发送到Retirement unit(指令毕业单元),不同类型的奔腾处理器包含不同数量的发送端口。
Retirement unit (指令退休毕业单元):
该单元从管道解码器和无序执行引擎中接收到所有需要执行的微操作,然后将这些微操作按传递过来的顺序交给execution unit(执行单元)去处理,并监测处理的结果,最后为了程序的正常执行,重组这些结果。
需要一个很大的缓冲区域来存放这些微操作的执行结果,并将它们按合适的顺序来存放。当一个微操作处理完毕,并且结果也按合适的顺序摆放好了,那么这个微操作就被认为退休或毕业了,然后就从Retirement unit(指令毕业单元)中移除,该单元还会更新指令分支预测单元里的信息,从而让其知道哪些指令处理过了,哪条跳转分支被采用了等。
也许你对上面的概念不太理解,不过汇编语言也操作不了这些东东,这些都是些固定的电路执行流程,每个处理器的具体实现也不一样,了解一下即可。
Execution unit (执行单元):
执行单元负责具体的执行处理某条指令,单个处理器中实际可以包含多个执行单元,使得处理器具有同时执行多条指令的能力。
每个执行单元又由一个或多个Arithmetic Logic Units(ALUs 算术逻辑单元)组成,算术逻辑单元专门用来处理不同类型数据的数学运算,奔腾4处理器执行单元中包含以下几种算术逻辑单元:
-
Simple-integer operations (简单整数运算)
-
Complex-integer operations (复杂整数运算)
-
Floating-point operations (浮点数运算)
Low-latency integer execution unit (低延迟整数运算执行单元):
该单元被设计成执行一些加法,减法,布尔操作等简单的整数运算,奔腾4处理器具有在一个时钟周期执行两个低延迟整数运算的能力,这有效的提高了处理速度。
Complex-integer execution unit (复杂整数运算执行单元):
该单元处理更复杂的整数运算,大多数shift(移位)和rotate(旋转)指令需要4个时钟周期来处理。乘除操作涉及较长的计算时间,通常需要14到60个时钟周期。
Floating-point execution unit (浮点运算执行单元):
IA-32家族中不同处理器之间的浮点执行单元都不同,所有的奔腾处理器都能使用标准的浮点执行单元来处理浮点运算,支持MMX和SSE的奔腾处理器也是在浮点执行单元中进行浮点运算的。
浮点执行单元里包含有寄存器可以处理64位到128位的数据,这使得计算中可以使用较大的浮点数,这样可以加快复杂浮点计算,如数字信号处理和视频压缩。
Registers (寄存器):
处理器的大部分操作都需要处理数据,但是不幸的是,从内存中存取数据是个相对于处理器来说很慢的操作,处理器将请求通过控制总线发送给内存单元,然后等待内存单元的响应,这个等待时间对于处理器来说是比较久的。
所以在处理器内部就有了寄存器这种组件,这样只要将数据存放到寄存器里,处理器需要时就可以直接从内部的寄存器中访问到数据,而不需要请求外部内存。不过,美中不足的是,处理器芯片内部的寄存器的数量是有限的。
IA-32平台的处理器有很多组不同尺寸的寄存器。不同处理器还包含一些特殊的寄存器,其中核心的寄存器组如下表所示:
Register 寄存器 |
Description 描述 |
General purpose
通用寄存器
|
Eight 32-bit registers used for storing working data
8个32位的寄存器用于常规的存储数据用。 |
Segment 段寄存器 |
Six 16-bit registers used for handling memory access
6个16位的用于处理内存访问的寄存器。 |
Instruction pointer
指令指针寄存器 |
A single 32-bit register pointing to the next
instruction code to execute
一个单一的指向下一条要执行的指令代码的寄存器。 |
Floating-point data
浮点寄存器 |
Eight 80-bit registers used for floating-point
arithmetic data
8个80位的寄存器,用于进行浮点计算。 |
Control 控制寄存器 |
Five 32-bit registers used to determine the
operating mode of the processor
5个32位的寄存器,用于检测判断处理器的操作模式 |
Debug 调试寄存器 |
Eight 32-bit registers used to contain information
when debugging the processor
8个32位的寄存器,当调试处理器时,包含相关调试信息。 |
|
下面对这些寄存器进行详细描述:
General-purpose registers (通用寄存器):
通用寄存器被用于临时存储数据,它们经历了从8位的8080处理器时代到32位的奔腾处理器的进化过程,每个通用寄存器都是向前兼容的,因此,那些用于8位8080处理器上的指令代码仍然可以在32位的奔腾处理器芯片上使用。
8个通用寄存器的常规用途如下表所示:
Register 寄存器 |
Description 描述 |
EAX |
Accumulator for operands and results data
用于操作数据和结果的累加器 |
EBX |
Pointer to data in the data memory segment
指向数据内存段中的数据的指针 |
ECX |
Counter for string and loop operations
用于字符串和循环操作中的计数器 |
EDX |
I/O pointer
I/O输入输出操作指针 |
EDI |
Data pointer for destination of string operations
指向字符串操作的目标操作数指针 |
ESI |
Data pointer for source of string operations
指向字符串操作的源操作数指针 |
ESP |
Stack pointer
栈指针 |
EBP |
Stack data pointer
栈数据指针 |
|
其中32位的EAX , EBX , ECX , EDX寄存器还具有16位和8位的名称来代表旧的低位寄存器,如下图1-2所示:
图1-2
通过使用AX就可以使用EAX寄存器的低16位的部分,通过引用AL,就可以使用EAX的低8位的部分,AH就可以使用紧挨着AL后的高8位的部分。
Segment registers (段寄存器):
段寄存器是专门用来引用内存位置的。IA-32处理器允许三种不同的访问系统内存的方式:
-
Flat memory model 平面内存模式
-
Segmented memory model 分段内存模式
-
Real-address mode 实地址模式
平面内存模式将所有的系统内存当作一个连续的地址空间。所有的指令,数据,栈都包含在相同的地址空间中。每个内存位置都通过线性地址来访问。
分段内存模式将系统内存划分为多个独立的段,通过段寄存器里的指针来引用不同的段,每个段用于包含一种特殊类型的数据,例如:一个段用于包含指令代码,另一个包含数据元素,还一个对应程序的栈。
分段内存模式通过逻辑地址来访问分段内存里的内存位置,一个逻辑地址由一个段地址和一个偏移地址组成,处理器会将逻辑地址翻译为线性地址来访问内存。下表显示了各种段寄存器的用途:
Segment Register
段寄存器 |
Description 描述 |
CS |
Code segment 代码段 |
DS |
Data segment 数据段 |
SS |
Stack segment 栈段 |
ES |
Extra segment pointer 额外数据段指针 |
FS |
Extra segment pointer 额外数据段指针 |
GS |
Extra segment pointer 额外数据段指针 |
|
每个段寄存器都是16位的,包含了指向特定内存段的起始位置,CS段包含了指向内存代码段的指针,代码段里存放的是指令代码。处理器以CS寄存器为基址,EIP寄存器的值为偏移,读取对应的指令来执行。程序里不能显式的加载或改变CS寄存器的值,处理器会在程序被赋予内存空间时,设置CS的值。
DS , ES , FS , GS段寄存器都用于指向数据元素,程序就有了四个数据段可用,程序必须为段寄存器加载合适的值,然后使用偏移值来访问指定内存。
SS段寄存器用于指向栈段,栈中包含了程序传递给函数的参数值。
实模式地址模式下,程序里所有的段寄存器都指向线性地址0,并且不被程序所改变。所有的指令代码,数据元素和栈元素都直接通过它们的线性地址来访问。
Instruction pointer register (指令指针寄存器):
指令指针寄存器即EIP寄存器,有时也被称作程序计数器,用于指向下一条要执行的指令代码(这里我们不考虑前面提过的指令预取缓存之类的东东,考虑也没什么含义,因为我们控制不了预取之类的操作)。
应用程序中不能直接修改EIP寄存器的值,必须通过跳转等指令来修改EIP的值。
在平面内存模式下,EIP存放的是下一条指令的线性地址,如果是分段内存模式,则EIP里存放的就是逻辑地址值,逻辑地址需要配合CS寄存器里的值来寻址。
Control registers (控制寄存器):
有5个控制寄存器,它们被用来检测处理器的操作模式,以及当前运行的任务的相关特征,下表显示了这5个控制寄存器的用途:
Control Register 控制寄存器 |
Description 描述 |
CR0 |
System flags that control the operating
mode and states of the processor
里面存放了系统标志,用于控制处理器的
操作模式和状态 |
CR1 |
Not currently used
当前并没使用 |
CR2 |
Memory page fault information
存放内存分页错误信息 |
CR3 |
Memory page directory information
存放内存分页目录信息 |
CR4 |
Flags that enable processor features and
indicate feature capabilities of the processor
该寄存器里的标志可以开启处理器的某些功能,并且可以从中知道处理器具有哪些功能和
能力。 |
|
控制寄存器里的值不能被直接访问,但是控制寄存器里的数据可以传递到通用寄存器里,然后程序就可以从通用寄存器里读取到这些值,然后根据这些值里的位标志来判断处理器或当前任务的操作状态。
如果要改变控制寄存器里的标志值,可以先在通用寄存器里进行修改,然后再由通用寄存器赋值给控制寄存器。一般是系统程序修改控制寄存器里的值的情况较多,普通用户程序很少会去修改控制寄存器,顶多就是从控制寄存器里查询一些标志来判断当前处理器芯片所具有的能力。
限于篇幅,本章节先到这里,下一节再将原著中IA-32平台章节的剩余部分翻译完。
OK,到这里,休息,休息一下 o(∩_∩)o~~