Li Jiaheng's blog
1222 字
6 分钟
汇编语言初步(4) 浮点数

浮点数的运算在一组与整数运算不同的寄存器上面执行,最新的成果被称为AVX(Advanced Vector Extension),高级向量扩展,这个体系中的寄存器名称是 %ymm0~%ymm15,它有256bits,可以存储4个64位数据或者8个32位数据。它的低128位名称为 %xmm0~%xmm15,来自于AVX的前一个迭代版本。
这组寄存器的本意是实现单指令多数据(SIMD, 读作sim-dee),如一个乘法指令同时处理多个地位相同的乘法。从意义上有点像numpy的所谓 “广播特性”,相当于多个数据被打包一个向量中同时并行计算
AVX寄存器中可以放多个整型或者浮点数,浮点数一定只能在AVX寄存器中处理。
C语言只进行标量处理,只用看%xmm即可(虽然GCC有应用向量计算的C语言扩展),后面指令中用 X 表示%xmm寄存器,用R 表示整数寄存器。

一、AVX寄存器用处设定#

%ymm0保存返回值(两用)
%ymm0~%ymm7按顺序保存8个参数。
剩下的是调用者保存

二、浮点数据传送#

操作数,对内存和寄存器值的引用和普通整型寄存器操作数完全一样。但是不支持浮点数的立即数(后面详细说)

浮点数传送指令:
(约定:M32为内存中32位空间,M64为内存中64位空间,ss是float,sd是double)

指令描述
vmovss M32 X传送单精度数到寄存器X
vmovss X M32方向和上面的反过来
vmovsd M64 X传送双精度数到寄存器X
vmovsd X M64方向和上面的反过来
vmovaps X X传送对齐封装好的单精度数(向量)
vmovapd X X传送对齐封装好的双精度数

三、类型转换#

1)单双精度浮点数类型转换(si是int,siq是long,2是to)
(VCVTT?)

指令描述
vcvttss2si X/M32 R32截断方法单精度转换为整数int
vcvttsd2si X/M64 R32截断方法双精度转换为整数int
vcvttss2siq X/M32 R64截断方法单精度转换为long
vcvttsd2siq X/M64 R64截断方法双精度转换为long
2)整数转浮点数(VCVT?)
指令效果
:-::-:
vcvtsi2ss M32/R32 X1 X2整数转换为单精度
vcvtsi2sd M32/R32 X1 X2整数转换为双精度
vcvtsi2ssq M64/R64 X1 X2long转换为单精度
vcvtsi2sdq M64/R64 X1 X2long转换为双精度

是少见的三操作数。其中第一个是源,第三个是目标寄存器,第二个只和高位有关,在C中用不上,可以忽略。
3)浮点数之间转换,很自然想到如下指令:
vcvtss2sd M/R X1 X2
这没有问题,但是GCC不会用这个,而是用了一个很奇怪的方法,此处省略。

//待转换浮点数在%xmm0中,见《深入理解计算机系统》P207  
vunpcklps %xmm0 %xmm0 %xmm0  
vcvtps2pd %xmm0 %xmm0  

四、浮点数运算#

1)浮点运算(运算前,要提前将数据扩展为范围较大的类型,同步)

指令 S1 S2 D效果
vaddss / vaddsdS1+S2—>D
vsubss / vsubsdS2-S1—>D
vmulss / vmulsdS1*S2—>D
vdivss / vdivsdS2/S1—>D
vminss / vminsdmin(S1,S2)—>D
vmaxss / vmaxsdmax(S1,S2)—>D

都是三操作数,都有单双精度版本。
特殊指令:平方根:

sqrtss / sqrtsd S1 Dsqrt(S1)—>D

2)浮点数位运算:

指令 S1 S2 D效果
vxorps / xorpdS1^S2—>D
vandps / andpdS1&S2—>D

同样有单双精度版本,注意双精度的没有v.

3)浮点立即数(即浮点常数)
浮点常数要保存在内存中,计算的时候由内存读取。但并不额外给多一个变量,而是存储这个数后,用一个标签(即地址*Operand)表示这个数在哪,而怎么读也有讲究。
如:

double cel2fahr(double temp)  
{  
	return 1.8 * temp + 32.0;  
}  

这个1.8和32.0放在内存中。在将1.8从内存中读到寄存器里进行下一步计算,会用如下机器代码:

	vmulsd .LC2(%rip), %xmm0, %xmm0;  
LC2:  
	.long 3435973837  //lower 4 bytes of 1.8  
	.long 1073532108  //higher 4 bytes of 1.8  

Intel机器是小端法,地址小的存低位,靠上的代码地址小,存低4字节。
从LC2计算浮点常数:这两个数都是10进制 的!把这两个十进制数无符号转换为4字节(8位)16进制数,从高四位中截取阶码,把高四位剩下的和低四位全部合在一起就成了需要的浮点数。

五、比较与条件码#

1)比较

指令原理描述
vucomiss S1,S2S2-S1比较单精度值
vucomisd S1,S2S2-S1比较双精度值

类似CMP族指令,会设置条件码。
2)条件码
零标志位ZF
进位标志位CF
奇偶标志位PF
最后一个就是对最低字节的奇偶校验。如果最低字节有偶数个1,则PF为1.
整数运算中也有,但是很少用。浮点运算中,PF可以用来判断两个操作数是否有任何一个是NaN

汇编语言初步(4) 浮点数
https://namisntimpot.github.io/posts/computersystem/汇编语言/汇编语言初步4浮点数/
作者
Li Jiaheng
发布于
2022-08-15
许可协议
CC BY-NC-SA 4.0