对于处理器所执行的每种操作都需要一种机制来判断该操作是否成功。而各种处理器的标志就可以完成这个功能,标志对于汇编程序来说是很重要的,因为它们是唯一可用的判断操作是否成功的方法。例如,程序中执行一个减法操作,如果结果为负数,那么处理器中的某个特定标志就会被设置...

    本文由zengl.com站长对
    http://pan.baidu.com/share/link?shareid=3717576860&uk=940392313 汇编教程英文版相应章节进行翻译得来。
    另外再附加一个英特尔英文手册的共享链接地址:
    http://pan.baidu.com/share/link?shareid=2345340326&uk=940392313 (在某些例子中会用到)

    本节对原著的IA-32平台章节的剩余部分进行翻译。

Flags (标志寄存器里的各种标志):

    对于处理器所执行的每种操作都需要一种机制来判断该操作是否成功。而各种处理器的标志就可以完成这个功能,标志对于汇编程序来说是很重要的,因为它们是唯一可用的判断操作是否成功的方法。例如,程序中执行一个减法操作,如果结果为负数,那么处理器中的某个特定标志就会被设置,用来表示结果为负。如果不检查这个标志,汇编程序就无法知道程序运行是否有误。

    IA-32平台使用一个32位的EFLAGS寄存器来包含各种状态,像控制和系统标志。这32位标志中,有些位是保留给以后的处理器用的,在原著编写的时候,有17位标志在被使用中。

    这些标志根据各自的作用,可以划分为三个组:
  • Status flags 状态标志
  • Control flags 控制标志
  • System flags 系统标志
    下面具体的描述这些标志:

Status flags (状态标志):

    这些状态标志用于指示处理器数学操作的结果,当前拥有的状态标志在EFLAGS寄存器中的位置和作用,如下表所示:

Flag 标志 Bit 所在位 Name 标志完整名称
CF 0 Carry flag 进位或借位标志
PF 2 Parity flag 奇偶标志
AF 4 Adjust flag 调整或辅助标志
ZF 6 Zero flag 结果是否为零标志
SF 7 Sign flag 符号标志
OF 11 Overflow flag 溢出标志

    Carry flag(进位或借位标志):如果对无符号整数进行数学操作,当操作使得无符号整数的最高位发生进位或借位时,则该标志位会被设置为1,此时保留在结果寄存器里的数是发生溢出了的,单凭结果寄存器里的数是无法知道正确的值的,这时就需要配合CF标志来得到正确的值。

    Parity flag(奇偶标志):这个标志可以用于简单的校验计算结果是否发生数据损坏,当结果寄存器中有偶数个位是1的话,该标志就会被设置为1,如果是奇数,则该标志位被清零,如结果是十进制102(对应二进制格式为1100110),这个结果的二进制格式中有4个位是1,那么奇偶标志就会被设置为1。

    Adjust flag(调整标志,也被称作Auxiliary flag 辅助标志):主要用于Binary Coded Decimal(即二进码十进数,简写为BCD码)的运算,(BCD的相关计算和概念将在后面的章节进行说明),当用于计算的寄存器里的值的位3(即第4位)发生了进位或借位操作时,该标志就会被设置为1。

    Zero flag(结果是否为零标志):顾名思义就是用于判断操作的结果是否为零,当结果为零时,该标志就会被设置。这是一种常用的又很简单的判断计算结果是否为零的方法。

    Sign flag(符号标志):该标志根据操作结果的最高位来判断结果是正数还是负数,如果是负数则该标志被设置。例如在一个8位系统中,如果操作结果是十进制-37,对应的二进制值为1101 1011,最高位为1,则符号标志会被设置为1 ,如果是十进制+37,对应二进制为0010 0101,最高位为0,则符号标志就会被清零。

    overflow flag(溢出标志):该标志主要用于有符号的整数运算中,当一个正数的值太大,或者一个负数的值太小时,就会发生溢出,该标志就会被设置。

Control flags (控制标志):

    控制标志用于控制处理器的特定行为。目前,只定义了一个控制标志,即DF标志(direction flag 方向标志),用于控制处理器处理字符串的方向,当该标志被设置为1时,字符串指令会自动以内存地址递减的方式,获取字符串的下一个字节,即从高地址读到低地址。当该标志被清零(即设置为0)时,则指令会以内存地址递增的方式,获取字符串的下一个字节,即从低地址读到高地址。

System flags (系统标志):

    系统标志主要用于控制操作系统级别的操作,普通应用程序不应该尝试去修改这些系统标志。当前可用的系统标志如下表所示:

Flag 标志 Bit 所在位 Name 标志完整名称
TF 8 Trap flag 陷阱标志
IF 9 Interrupt enable flag 中断开启标志
IOPL 12 and 13 I/O privilege level flag I/O优先级标志
NT 14 Nested task flag 嵌套任务标志
RF 16 Resume flag 恢复标志
VM 17 Virtual-8086 mode flag 
虚拟8086模式标志
AC 18 Alignment check flag 对齐检查标志
VIF 19 Virtual interrupt flag 虚拟中断标志
VIP 20 Virtual interrupt pending flag 
虚拟中断挂起标志
ID 21 Identification flag 识别标志

    Trap flag(陷阱标志):用于开启单步执行模式,在单步执行模式下,处理器一次只能执行一条指令,只有收到特殊信号时才执行下一条指令。这个功能在调试汇编程序时非常有用。

    Interrupt enable flag(中断开启标志,简写为IF标志):用于控制处理器,是否响应从外部设备接收到的信号。当IF设为1时,可屏蔽中断就会被处理,当为0时,可屏蔽中断就会被忽略(非可屏蔽中断和INT指令对应的软件中断不受IF标志的影响)。

    IOPL是I/O保护机制中的关键之一,它位于EFLAGS寄存器的第12、13位。指令in、ins、out、outs、cli、sti只有在CPL(当前任务的优先级)<= IOPL时才能执行。这些指令被称为I/O敏感指令,如果特权级低的指令试图访问这些I/O敏感指令将会导致常规保护错误(#GP)。可以改变IOPL的指令只有popfl和iret指令,但只有运行在特权级0的程序才能将其改变。

    Nested task flag(嵌套任务标志):用于保护模式,当该标志被设置为1时,表明一个系统任务已经通过CALL指令而非JMP指令调用了另一个任务。

    Resume flag(恢复标志):当处理器处于调试模式时,通过该标志来控制处理器响应异常的方式。

    Virtual-8086 mode flag(虚拟8086模式标志):该标志标明处理器运行在虚拟8086模式下,而非保护模式和实模式下,在虚拟8086模式下,处理器表现的就像一个高速的8086处理器一样。

    Alignment check flag(对齐检查标志):该标志和CR0控制寄存器的AM位一起,用于开启内存对齐检查机制,在开启了该机制的情况下,当处理器访问未对齐的内存数据时,就会出现数据未对齐的异常。

    Virtual interrupt flag(虚拟中断标志):用于虚拟8086模式下,代替IF标志。

    Virtual interrupt pending flag(虚拟中断挂起标志):用于虚拟8086模式下,表明当前有一个或多个中断等待处理。

    Identification flag(识别标志):用于表明当前处理器是否支持CPUID指令,如果该标志可以被设置或清零,就表示当前处理器支持CPUID指令,否则就不支持,CPUID指令前面提到过可以用于检测当前处理器的供应商,型号等信息。

Advanced IA-32 Features (高级的IA-32功能):

    前面提到的IA-32平台的核心功能,在从80386开始的处理器系列中都可用。下面就介绍些高级的功能,汇编程序员在给奔腾处理器开发程序时,可以用到这些功能。

The x87 floating-point unit (x87浮点执行单元):

    IA-32家族早期的处理器需要一个额外的协处理器芯片来执行浮点数的数学运算。80287和80387处理器就是专门用来提供浮点运算的电脑芯片。如果程序员需要快速的处理浮点运算的话,就被迫需要额外的芯片硬件来支持他们的需求。

    从80486处理器开始,80287和80387芯片的高级运算功能被添加到主处理器中,当然需要支持这些功能,就需要在处理器中增加额外的指令代码,以及相关的寄存器和执行单元。这些元素合在一起被称作x87浮点单元(简写为FPU)。

    x87 FPU中包含下面这些额外的寄存器:

FPU Register 
FPU寄存器
Description 
描述
Data registers 
数据寄存器
Eight 80-bit registers for floating-point data 
8个80位的用于浮点数的寄存器
Status register 
状态寄存器
16-bit register to report the status of the FPU 
16位寄存器用于反映FPU的状态
Control register 
控制寄存器
16-bit register to control the precision of the FPU 
16位寄存器用于控制FPU的精度
Tag register 
标签寄存器
16-bit register to describe the contents of the 
eight data registers 
16位寄存器用于描述八个数据寄存器的内容
FIP register 
FIP寄存器
48-bit FPU instruction pointer (FIP) points to the next FPU instruction 
48位的FPU指令指针寄存器,用于指向
下一条要执行的FPU指令
FDP register 
FDP寄存器
48-bit FPU data pointer (FDP) points to the data in memory 
48位的FPU数据指针寄存器,用于指向内存中的数据
Opcode register 
操作码寄存器
11-bit register to hold the last instruction 
processed by the FPU 
11位寄存器用于保存FPU最后处理过的指令

    FPU相关的寄存器和指令代码让汇编程序可以快速的处理复杂的浮点运算功能,例如那些图像处理,数字信号处理,及复杂的商业应用等。FPU处理浮点运算的速度,要比普通的没有FPU的处理器采用软件模拟的方式要快很多,因此,汇编程序员应该尽可能的使用FPU来进行浮点运算。

Multimedia extensions (多媒体扩展 MMX):

    奔腾2处理器开始,为程序员提供了另一种处理复杂整数运算的方法,即MMX,MMX是第一个支持英特尔单指令多数据模式(英文全称:Intel Single Instruction, Multiple Data,简写为SIMD)的技术。

    SIMD模式的开发是为了处理更大的数字,这种情况在多媒体应用中比较常见。SIMD使用扩展的寄存器的大小和新的数字格式,以加快复杂的数字运算,从而满足多媒体实时展示的需求。

    MMX包含三种新的浮点数据类型:
  • 64-bit packed byte integers 64位压缩字节整数
  • 64-bit packed word integers 64位压缩字整数
  • 64-bit packed doubleword integers 64位压缩双字整数
    这些数据类型将在后面的章节中进行描述,为了处理这些新的数据格式,MMX技术集成了八个FPU专用寄存器,即MM0 , MM1...... MM7这八个寄存器。它们被用于64位压缩的整数的运算。

    尽管MMX技术加快了复杂整数的运算速度,但是它对复杂浮点数的运算并没什么改进,这个问题在下面要介绍的SSE技术中得到改善。

Streaming SIMD extensions (SSE):

    奔腾3处理器引入了新的SIMD技术,即SSE技术,SSE增强了复杂浮点数的运算能力,这些运算通常用于3-D图形,动态视频,视频会议等。

    SSE包含八个新的128位的寄存器(被称作XMM0 , XMM1 ........ XMM7),以及引进了新的数据类型,即128-bit packed single-precision floating point (128位压缩的单精度浮点数据类型)。另外还包含了一些新的指令代码,这些指令可以在一个单一的指令中,处理多达4个的128位压缩单精度浮点数。

    奔腾4处理器实现了第二代SSE技术,即SSE2,SSE2使用和SSE相同的XMM寄存器,同时包含了5种新的数据类型:
  • 128-bit packed double-precision floating point 128位压缩双精度浮点数据类型
  • 128-bit packed byte integers 128位压缩字节整数
  • 128-bit packed word integers 128位压缩字整数
  • 128-bit packed doubleword integers 128位压缩双字整数
  • 128-bit packed quadword integers 128位压缩四字整数
    这些数据类型也将在后面的章节中进行详述。这些新的数据类型和相关的指令代码让程序员可以利用它们来处理更复杂的数学运算,其中128位双精度浮点数据类型,可以用于先进的3-D几何技术,例如以最小的处理器时间进行射线追踪等。

    SSE3(第三代SSE技术)并没有引入新的数据类型,但是提供了些新的指令,这些指令可以在XMM寄存器中同时处理整数和浮点数。

Hyperthreading (超线程):

    在奔腾4处理器中添加的最令人兴奋的功能之一就是超线程。超线程让IA-32处理器可以同时处理多个程序的执行线程。

    超线程技术中,单个物理处理器里包含两个或更多的逻辑处理器。每个逻辑处理器都包含一套完整的通用寄存器,段寄存器,控制寄存器及调试寄存器。所有的逻辑寄存器共享相同的执行单元,Out-of-Order无序执行引擎负责处理多个逻辑处理器提供的不同线程的指令。

    超线程技术在操作系统层的优势比较显著,例如微软windows系统,各种UNIX系统及变种系统,可以将应用程序的线程分配到不同的逻辑处理器中。对于普通应用程序,超线程的好处就没那么明显了。

The IA-32 Processor Family (IA-32处理器家族):

    英文原著编写的时候,IA-32家族的处理器可以说是各大工作站和服务器上使用的最流行的电脑平台了,windows ,linux等系统都可以在IA-32平台上运行,前面的内容介绍的是IA-32家族处理器的通用的核心功能,下面介绍下IA-32家族中不同的处理器,了解这些不同类型的处理器将有助于在这些平台上开发汇编程序。

Intel processors (英特尔处理器):

    英特尔可以说是IA-32平台处理器的主要供应商,在原著写作的时候,最流行的应该是奔腾处理器了。然而,在各大学校,企业,家庭中又有多种不同类型奔腾处理器在运行,如果你的程序采用了那些只在最新处理器中才有的功能的话,那么你的程序的销量肯定会受影响。相反,如果你的程序能够根据不同的处理器平台,使用不同的功能的话,那么你的程序就会受到欢迎。下面就介绍下不同类型的奔腾处理器。

The Pentium processor family (最原始的奔腾处理器家族):

    最原始的奔腾处理器出现在1993年,是80486处理器的替代品,奔腾处理器是第一个集成双执行管道的处理器,也是第一个使用完整的32位地址总线和64位内部数据路径的处理器。

    尽管第一款奔腾处理器的性能优势是显而易见的,然而,从编程的角度来看,最开始的奔腾处理器并没提供比80486体系架构更多的新功能,所有80486上的寄存器和指令以及内部的FPU支持,都可以在奔腾处理器上使用。

The P6 processor family (P6处理器家族):

    P6处理器家族是在1995推出的奔腾Pro处理器,奔腾Pro处理器加入了和原来的奔腾处理器完全不同的全新的体系结构,P6系列处理器是首个利用了superscalar microarchitecture (超标量微架构)的处理器,通过使用多个执行单元和指令预取管道,大大提升了性能。

    奔腾MMX和奔腾2处理器,作为P6家族的一部分,是第一个引入MMX技术的处理器,还引入了新的低功耗状态,使处理器在空闲时可以进入睡眠模式,此功能有助于节省电能,并且成为了笔记本电脑的理想平台。

    奔腾3处理器则是首个引入了SSE技术的处理器,这让程序员可以很轻松,快捷的处理复杂的浮点运算。

The Pentium 4 processor family (奔腾4处理器家族):

    奔腾4处理器在2000年被推出,并且是微处理器设计的又一次新的尝试,奔腾4处理器采用英特尔NetBurst架构,这种架构采用指令流水线,无序执行核心以及相关的执行单元来达到更快的处理速度。

    奔腾4处理器支持SSE3,即SSE的扩展技术,提供更多的浮点计算能力,以支持高速的多媒体计算。

The Pentium Xeon processor family (奔腾Xeon处理器家族):

    2001年,英特尔推出了奔腾Xeon处理器,它主要用于多处理器服务器操作。它支持MMX,SSE,SSE2,SSE3技术。

Non-Intel processors (非英特尔系列的处理器):

    虽然IA-32平台往往被认为是英特尔的事情,但是市面上仍然有很多非英特尔的处理器,这些处理器也实现了IA-32平台的功能,这让你的汇编程序可以运行在非英特尔的平台上,所以你有必要知道一些这些平台之间的差异。

AMD processors (AMD处理器):

    如今,英特尔最大的竞争对手就是AMD,AMD发布了一系列和英特尔奔腾处理器竞争的处理器芯片。运行在AMD平台上的windows系统工作站也不少。下表显示了AMD处理器的历史:

AMD Processor 
AMD处理器
Equivalent to 
等效的奔腾处理器
Notes 备注
K5 Pentium 
原始的奔腾处理器
100% software compatible 
100%软件兼容
K6 Pentium MMX 
奔腾MMX
Pentium with full MMX support 
完全支持MMX的奔腾处理器
K6-2 Pentium II 奔腾2 Uses 3D Now technology AMD使用的是和SSE等效的3D Now,还不支持SSE指令
K6-III Pentium III 奔腾3
 
Athlon Pentium 4 奔腾4
 
Athlon XP Pentium 4 w/SSE 
奔腾4,支持SSE
AMD开始支持SSE指令

    对应汇编程序员来说,AMD和英特尔处理器之间最重要的不同在于所使用的SIMD技术。尽管AMD已经重复了MMX技术,但是它并没完全重复新的SSE技术,当英特尔在奔腾2处理器中引入SSE时,AMD则采用了另一种不同的路线。AMD K6-2处理器使用的SIMD技术被称作3D Now技术。3D Now技术使用和SSE类似的寄存器和数据类型,但是它并不是软件兼容的。这导致那些想使用SSE功能的程序员,在AMD和英特尔的兼容上遇到相当大的困难。

    当2001年Athlon XP处理器发布的时候,AMD开始支持SSE的整数运算。在原著编写的时候,最新的AMD处理器芯片已经完全支持SSE技术。

Cyrix processors (Cyrix处理器):

    尽管Cyrix公司有好几年没运作了,但是他们的IA-32平台的处理器仍然可以在许多工作站及低端服务器中看到。所以你的程序还是有可能会接触到Cyrix处理器。

    Cyrix处理器家族的演变,反映了许多版本的英特尔处理器。Cyrix生产的第一个奔腾级别的处理器最初被称作6x86处理器,它与原始的奔腾处理器是100%软件兼容的。当英特尔引入MMX技术时,Cyrix对应生产了6x86MX处理器(他们没有使用MMX名称的许可,不过MX这个名称也足够说明这层意思了)。

    当Cyrix被VIA威盛公司收购后,原来的Cyrix处理器产品线就被重命名了,6x86处理器被重命名为M1,另外6x86MX被重命名为M2,另外这些处理器依然保持着对奔腾处理器的兼容性。

    Cyrix处理器在消亡之前,最后一个版本即Cyrix 3被推向了市场。它是与奔腾3相兼容的,不过不幸的是,和AMD类似,它不得不使用3D Now技术来支持SSE,这导致使用了SSE的汇编程序将与该处理器不兼容。

    最后就是本章总结,总结部分就不翻译了,就是前面内容的炒现饭。这几章介绍了汇编语言的硬件环境,下一章就将讨论汇编语言的软件开发环境。原著作者使用的是Linux操作系统下的汇编开发工具来进行汇编教学的,在Linux下,基于GNU协议,将让你得到一个廉价的软件开发环境。

    OK,到这里,休息,休息一下 o(∩_∩)o~~
上下篇

下一篇: 汇编开发相关工具 (一)

上一篇: IA-32平台(二)

相关文章

IA-32平台(一)

汇编函数的定义和使用 (一)

使用内联汇编 (一)

使用内联汇编 (二)

高级数学运算 (一) FPU寄存器介绍

汇编字符串操作 (一)