- 浏览: 142345 次
文章分类
最新评论
上一节介绍了浮点数与各种数值类型之间的相互转换所用到的指令,本节则介绍进行各种浮点运算所需的指令。
先来看看下面一组用于执行算术运算的标量 AVX2 浮点指令。
其中,每条指令有一个或两个源操作数 S1、S2,以及一个目的操作数 D。第一个源操作数 S1 可以是一个 XMM 寄存器或一个内存位置,而第二个源操作数和目的操作数都必须是 XMM 寄存器。每个操作都有一条针对单精度和一条双精度的指令。结果都存放在目的寄存器中。
考虑下面的浮点 C 函数。
其对应的 x86-64 代码类似如下。
不同于整数操作,AVX 浮点操作不能以立即数值作为操作数。相反,编译器必须为所有的常量值分配和初始化存储空间,然后再把这些值从内存读入。下面这个从摄氏度到华氏度转换的函数说明了这个问题。
在采用小端字节顺序的机器上生成的 x86-64 汇编代码类似如下。
可以看到,值 1.8 是从标号为“.LC2”内存位置处读出,值 32.0 是从标号“.LC3”内存位置处读出。而这些标号对应的值,每一个都是通过一对“.long”声明和十进制表示的值指定的。要理解这些数所表示的浮点值,需要知道浮点数在系统底层的表示方法,具体可以参考《深入理解计算机系统》第二章——信息的表示和处理,碍于篇幅限制,这里只给出结论。以标号“.LC2”的两个数值为例,因为机器采用的是小端字节顺序,所以第一个值 3435973837(0xcccccccd)给出的是低位 4 字节,第二个值 1073532108(0x3ffccccc)给出的是高位 4 字节。从高位字节抽取指数字段为 0x3ff(1023),减去偏置值 1023 得到指数 0,将两个值的小数位连接起来,得到小数字段 0xccccccccccccd,二进制小数表示为 0.8,加上隐含的 1 就得到 1.8。
除了进行普通运算操作,GCC 生成的代码还可以在 XMM 寄存器上执行位级操作。下图所示的指令会对一个 XMM 寄存器中的所有 128 位进行位操作,不过同前面一样,我们一般只关心目的寄存器的低 4 或 8 字节。
另外,AVX2 还提供了两条用于比较浮点数值的指令。
这里的操作数 S2 必须在 XMM 寄存器中,而 S1 还可以在内存中。这两条指令类似于 CMP 指令,也是通过设置条件码来指示它们的相对值。浮点比较指令会设置三个条件码:零标志位 ZF、进位标志位 CF 和奇偶标志位 PF。PF 标志位在 GCC 产生的 x86 代码中不太常见,对于整数操作,当最近的一次算术或逻辑运算产生的值的最低位字节是偶校验的(即这个字节中有偶数个 1),那么就会设置这个标志位。而对于浮点数,当两个操作数中任一个是 NaN 时,就会设置该位。这个标志位就是用来发现是否有参数为 NaN 的情况,因为当 x 为 NaN 时,比较 x==x 都会得到 0,表示比较失败。
条件码的设置条件如下。
当任一操作数为 NaN 时,就会出现图中无序的情况。通常 jp(jump on parity) 指令是条件跳转,条件就是浮点比较得到一个无序的结果。进位和零标志位的使用同整数的一样,这里不再赘述。
参考书籍:
1、《深入理解计算机系统》第三章——程序的机器级表示。
先来看看下面一组用于执行算术运算的标量 AVX2 浮点指令。
其中,每条指令有一个或两个源操作数 S1、S2,以及一个目的操作数 D。第一个源操作数 S1 可以是一个 XMM 寄存器或一个内存位置,而第二个源操作数和目的操作数都必须是 XMM 寄存器。每个操作都有一条针对单精度和一条双精度的指令。结果都存放在目的寄存器中。
考虑下面的浮点 C 函数。
double funct(double a, float x, double b, int i){ return a*x - b/i; }
其对应的 x86-64 代码类似如下。
; double funct(double a, float x, double b, int i); ; a in %xmm0, x in %xmm1, b in %xmm2, i in %edi funct: ; The following two instructions convert x to double vunpcklps %xmm1, %xmm1, %xmm1 vcvtps2pd %xmm1, %xmm1 vmulsd %xmm0, %xmm1, %xmm0 ; Multiply a by x vcvtsi2sd %edi, %xmm1, %xmm1 ; Convert i to double vdivsd %xmm1, %xmm2, %xmm2 ; Compute b/i vsubsd %xmm2, %xmm0, %xmm0 ; Subtract from a*x ret ; Return
不同于整数操作,AVX 浮点操作不能以立即数值作为操作数。相反,编译器必须为所有的常量值分配和初始化存储空间,然后再把这些值从内存读入。下面这个从摄氏度到华氏度转换的函数说明了这个问题。
double cel2fahr(double temp){ return 1.8 * temp + 32.0; }
在采用小端字节顺序的机器上生成的 x86-64 汇编代码类似如下。
; double cel2fahr(double temp) ; temp in %xmm0 cel2fahr: vmulsd .LC2(%rip), %xmm0, %xmm0 ; Multiply by 1.8 vaddsd .LC3(%rip), %xmm0, %xmm0 ; Add 32.0 ret .LC2: .long 3435973837 ; Low-order 4 bytes of 1.8 .long 1073532108 ; High-order 4 bytes of 1.8 .LC3: .long 0 ; Low-order 4 bytes of 32.0 .long 1077936128 ; High-order 4 bytes of 32.0
可以看到,值 1.8 是从标号为“.LC2”内存位置处读出,值 32.0 是从标号“.LC3”内存位置处读出。而这些标号对应的值,每一个都是通过一对“.long”声明和十进制表示的值指定的。要理解这些数所表示的浮点值,需要知道浮点数在系统底层的表示方法,具体可以参考《深入理解计算机系统》第二章——信息的表示和处理,碍于篇幅限制,这里只给出结论。以标号“.LC2”的两个数值为例,因为机器采用的是小端字节顺序,所以第一个值 3435973837(0xcccccccd)给出的是低位 4 字节,第二个值 1073532108(0x3ffccccc)给出的是高位 4 字节。从高位字节抽取指数字段为 0x3ff(1023),减去偏置值 1023 得到指数 0,将两个值的小数位连接起来,得到小数字段 0xccccccccccccd,二进制小数表示为 0.8,加上隐含的 1 就得到 1.8。
除了进行普通运算操作,GCC 生成的代码还可以在 XMM 寄存器上执行位级操作。下图所示的指令会对一个 XMM 寄存器中的所有 128 位进行位操作,不过同前面一样,我们一般只关心目的寄存器的低 4 或 8 字节。
另外,AVX2 还提供了两条用于比较浮点数值的指令。
这里的操作数 S2 必须在 XMM 寄存器中,而 S1 还可以在内存中。这两条指令类似于 CMP 指令,也是通过设置条件码来指示它们的相对值。浮点比较指令会设置三个条件码:零标志位 ZF、进位标志位 CF 和奇偶标志位 PF。PF 标志位在 GCC 产生的 x86 代码中不太常见,对于整数操作,当最近的一次算术或逻辑运算产生的值的最低位字节是偶校验的(即这个字节中有偶数个 1),那么就会设置这个标志位。而对于浮点数,当两个操作数中任一个是 NaN 时,就会设置该位。这个标志位就是用来发现是否有参数为 NaN 的情况,因为当 x 为 NaN 时,比较 x==x 都会得到 0,表示比较失败。
条件码的设置条件如下。
当任一操作数为 NaN 时,就会出现图中无序的情况。通常 jp(jump on parity) 指令是条件跳转,条件就是浮点比较得到一个无序的结果。进位和零标志位的使用同整数的一样,这里不再赘述。
参考书籍:
1、《深入理解计算机系统》第三章——程序的机器级表示。
发表评论
-
浮点数类型转换指令
2019-05-15 22:37 1709在浮点寄存 ... -
浮点寄存器概述
2019-05-14 22:31 2589本文介绍的浮点寄存器是基于 AVX2(Adva ... -
汇编指令之跳转指令
2019-04-15 00:21 4798正常执行的情况下,指令会按照顺序一条条地执行, ... -
汇编指令之条件码
2019-04-08 21:05 2359在系统底层,除了整数寄存器,CPU 还维护着一 ... -
汇编指令之算术和逻辑操作指令
2019-03-28 22:16 1382下表是 x86-64 ... -
汇编指令之数据传送指令
2019-03-25 21:28 1288在x86-64 中的 ... -
x86-64 中的寄存器与汇编操作数杂述
2019-03-20 21:45 993Intel 中常用 ... -
hello 程序执行背后的故事
2018-12-26 21:48 608源文件 hello. ... -
linux启动服务概述
2017-04-08 02:43 398传统的linux中定义了七个运行级,分别如下: ... -
unix限制
2017-04-04 16:08 578UNIX系统实现定义了很多幻数和常量,其中有很 ... -
linux引导加载程序--GRUB
2017-04-04 04:22 625linux世界里有两种 ... -
存储器映射
2016-06-13 00:12 553注:本文摘自《深入理解计算机操作系统》第九章--虚拟存 ... -
虚拟存储器对存储器管理的作用
2016-06-10 16:00 695注:本文中的大部分内容均是摘录自《深入理解计算机系统》一书,权 ... -
信号处理问题
2016-06-03 08:31 561注:本文摘自《深入理解计算机系统》第8章 --- 异常控制流。 ... -
僵尸进程
2016-05-23 23:57 361在解释僵尸进程的概念之前,我们得先了解这样的一个事实: 一个进 ... -
程序优化之存储器别名使用
2016-05-20 08:55 797说明:本文示例摘自《深入理解计算机系统》第五章----优化程序 ... -
条件变量基本概念与原理(转载)
2016-05-20 08:54 1579对于条件变量,我一直感到很困惑,搞不清其与互斥锁到底有啥区别, ... -
CPU与磁盘的交互过程
2016-05-19 09:05 1839对于计算机系统底层技术,想必很多人都和我一样不太了解,最近在学 ... -
存储器层次结构中基本的缓存原理
2016-05-19 09:00 668对于操作系统,我们知道,越靠近CPU的存储器,其存储速度就会越 ... -
异常处理
2016-05-19 00:29 424我知道很多人都知道异常处理,但可能对其底层并不太了解,现在我们 ...
相关推荐
FP系列浮点运算指令是计算机科学中的一个重要领域,特别是在处理器设计和编程中。浮点运算主要涉及浮点数(即带有小数部分的数字)的数学运算,如加法、减法、乘法和除法。这些运算在科学计算、图形处理、物理模拟等...
浮点运算指令速查手册是IT领域中针对处理器浮点计算的一份重要参考资料,它包含了大量用于处理浮点数据和进行浮点运算的指令。这些指令对于编程、编译器优化以及高性能计算至关重要,因为它们直接影响到计算精度和...
【浮点运算指令编译器设计】涉及到计算机科学中的编译器原理和浮点数处理。编译器是编程过程中的关键工具,它将高级编程语言转换为机器可执行的低级指令。在这个特定的毕业设计中,编译器专注于处理浮点运算指令,这...
本文将深入探讨“浮点运算样本程序”这一主题,主要针对三菱PLC,结合提供的压缩包文件“复件 浮点运算”,我们将讨论浮点数运算在PLC中的应用、浮点数数据类型、三菱PLC的浮点运算指令以及如何在实际项目中使用这些...
Linux内核对于浮点运算的支持主要分为两种情况:带有浮点运算单元(FPU)的处理器和不带FPU的处理器。浮点运算单元通常用于处理浮点数计算,提高科学计算和图形处理等领域的效率。 对于带有FPU的处理器,如X86架构...
在许多实际应用中,浮点运算的需求日益增强,例如在数学计算、信号处理等领域。STC15系列单片机虽然基于传统的8位架构,但通过内置硬件支持或软件库的方式,也能实现浮点运算功能。本文将详细探讨STC15系列单片机的...
### 运算指令详解 #### 向量运算 - **乘法**:`VMUL{C}.<P>Fd,Fn,Fm`,该指令将`Fn`和`Fm`相乘的结果存储在`Fd`中。 - **乘法并求反**:`VNMUL{C}.<P>Fd,Fn,Fm`,相当于`Fd:=- (Fn*Fm)`。 - **并累加**:`VMLA{C}....
汇编语言编程能够充分利用处理器的指令集,减少指令开销,从而提高代码执行效率,尤其是在处理浮点运算时效果显著。 这个库包含了各种常见的浮点数学函数,如加减乘除、指数、对数、三角函数等。这些函数在库中被...
硬浮点是指处理器具有硬件浮点运算单元,可以直接执行浮点运算指令,提供更高的计算速度;而软浮点则是通过软件模拟浮点运算,效率较低,但可以节省硬件资源。在编译时,可以通过`-mfpu`和`-mfloat-abi`选项来选择...
在计算机科学领域,特别是对于基于Intel 80X86架构的处理器而言,掌握浮点运算指令是理解底层硬件工作原理的关键之一。浮点指令集是用于处理浮点数(实数)的一种指令集,它支持多种数学运算,包括但不限于加法、...
浮点定制指令是指在FPGA中针对浮点运算进行优化的一类特殊指令,这些指令可以显著提高系统在处理浮点计算任务时的效率和性能。Nios II是Altera公司(现被Intel收购)推出的一种软核CPU,它可以在FPGA中集成,支持...
浮点运算在计算机科学中扮演着至关重要的角色,尤其是在数值计算和科学计算领域。...在实际编程中,还需要考虑性能优化,例如使用硬件浮点运算指令,以及在必要时使用更精确的数据类型,如双精度浮点数。
总结来说,STM32 硬件浮点使用方法需要在系统初始化时启用 FPU,并在编译时添加启用 FPU 的语句,在使用 FPU 进行浮点运算时,需要使用固件库自带的 arm_math.h 头文件,这将提高浮点运算的效率。
与此相关的NEON指令集则进一步添加了SIMD操作,实现了NEON媒体处理器引擎的功能,它基于VFPv3指令集的浮点运算单元提供了更高级别的性能。 对于Toradex Colibri产品系列来说,不同型号的产品提供了不同的协处理器/...
在ARM指令集中,常见的指令类型包括数据处理指令、分支指令、加载/存储指令、浮点运算指令以及向量浮点运算指令等。 1. **数据处理指令**:包括算术运算(如加、减、乘、除)、逻辑运算(如与、或、非、异或)和...
ARM指令集通常分为几大类,包括数据处理指令、加载/存储指令、分支指令、浮点运算指令、向量浮点运算指令(在某些高级架构如ARMv8-A中)、系统指令等。 1. 数据处理指令:这些指令用于执行算术和逻辑操作,如加法...
这是因为浮点数的下溢处理是硬件级别的操作,通常由处理器的浮点运算单元(FPU)直接处理,改变这种处理方式可能涉及到处理器架构的重大调整。 2. 对计算机系统结构来说,不透明的是【D】指令采用硬联逻辑实现还是微...
3. **浮点运算指令**:随着移动设备对多媒体和科学计算需求的增长,浮点运算指令在ARM处理器中的地位越来越重要。ARM汇编支持单精度和双精度浮点运算,为处理浮点数提供了高效手段。 4. **内存访问指令**:包括加载...