《深入理解计算机系统》学习(8):浮点数和浮点代码

一、浮点数

浮点表示对形如V=x*2y的有理数进行编码,对执行涉及非常大的数字、非常接近0的数字和作为实数运算的近似值的计算,是很有用的。

1.1 二进制小数

十进制表示法使用如下形式的表示:dmdm-1…d0.d-1…dn。其中每个十进制数di的取值范围是0 ~ 9。数字权的定义与十进制小数点符号相关,这意味着小数点左边的数字的权是10的正幂,得到整数值,而小数点右边的数字的权是10的负幂,得到小数值。

例如,12.3410表示数字1 * 101+2 * 100+3 * 10-1+4 * 10-2=12 34 100 \frac{34}{100} 10034

请添加图片描述
类似的,二进制表示法每个二进制数字(位),小数点左边的数字的权是2的正幂,得到整数值,而小数点右边的数字的权是2的负幂,得到小数值。

例如,1011.12表示数字1 * 23+0 * 22+1 * 21+1 * 20+1 * 2-1=11 1 2 \frac{1}{2} 21

在仅考虑有限长度编码的情况下,十进制表示法不能准确的表示像 1 3 \frac{1}{3} 31 5 7 \frac{5}{7} 75这样的数。类似的,小数的二进制表示法只能表示那些能够被写成x*2y的数,其它的值只能被近似地表示。

1.2 IEEE浮点表示

定点表示法不能有效地表示非常大的数字。例如,表达式5*2100是用101后面跟随100个零的位模式来表示。IEEE浮点标准通过给定x和y的值,来表示形如x * 2y的数。

IEEE浮点标准用V=(-1)s * M * 2E 的形式来表示一个数。根据sME将浮点数的位表示划分为三个字段,分别对这些值进行编码。

  • 符号s决定该数是负数还是正数,由一个单独的符号位s直接编码。
  • 尾数M是一个二进制小数,由n位小数字段frac编码。
  • 阶码E的作用是对浮点数加权,这个权重是2的E次幂,由k位的阶码字段exp编码。

在单精度浮点格式(C语言中的float)中,s、exp、frac字段分别为1、8、23;在双精度浮点格式(C语言中的double)中分别为1、11、52。
请添加图片描述
根据exp的值,被编码的值可以分成三种不同的情况。
(1)规格化的值:exp不全为0,也不全为1。
阶段字段被解释为以偏置形式表示的有符号整数,阶码的值为E=e-Bias。其中e是阶段位向量(ek-1…e1e0)表示的无符号数(1 ~ 254;1 ~ 2046),而Bias是值为2k-1-1的偏置值(127;1023)。两者之差的结果为指数的取值范围。对于单精度浮点来说是-126 ~ 127,而对于双精度浮点来说是-1022 ~ 1023。

小数字段frac被解释为描述小数值f,f的范围为[0,1],二进制表示为0.fn-1…f1f0。而尾数M定义为1+f,所以M为1.fn-1…f1f0。使用这种方法获得一个额外的精度位,既然第一位总是等于1,就不需要显式地表示。

(2)非规格化的值:exp全为0
此时,阶码值是E=1-Bias,而尾数的值是M=f,也就是小数字段的值,不包含隐含的开头的1。

非规格化数有两个用途:
1、表示数值0。规格化的M总是大于等于1,因此不能用来表示0。符号位不同得到的+0和-0在某些方面是不同的。
2、表示非常接近于0.0的数。

(3)特殊值:exp全为1
此时,阶码全为1。
1、当小数域全为0时,得到的值表示无穷,s=0时表示正无穷,s=1时表示负无穷。无穷能表示溢出的结果,例如,两个非常大的数相乘或者除以零时。
2、当小数域为非零时,结果值被称为NaN,即不是一个数(Not a Number)的缩写。一些运算的结果不能是实数或无穷时返回NaN值。例如,极端 − 1 2 \sqrt[2]{-1} 21 ∞ \infty - ∞ \infty
请添加图片描述

1.3 C语言中的浮点数

所有的C语言版本提供了两种不同的浮点数据类型:float和double。在支持IEEE浮点格式的机器上,这些数据类型对应于单精度和双精度浮点。C语言标准不要求机器使用IEEE浮点,所以没有标准的方法改变舍入方式,或者得到-0、+ ∞ \infty 、- ∞ \infty 或者NaN之类的特殊值。

当在int、float和double格式之间进行强制转换时,程序改变数值和位模式的原则如下:

  • 从int转换为float,数字不会溢出,但是可能被舍入。
  • 从int或float转换为double,能够保留精确的数值。
  • 从double转换为float,值可能会溢出或者舍入。
  • 从float或者double转换为int,值将会向零舍入。

二、浮点代码

2.1 浮点体系结构

MMX技术,即MultiMedia eXtensions(多媒体拓展),在CPU中加入特地为视频信号、音频信号以及图像处理而设计的57条指令。这些指令的本意是允许多个操作以并行模式执行,称为单指令多数据或SIMD,在这种模式中,对多个不同的数据并行执行同一个操作。从MMX发展到SSE(Streaming SIMD Extension),以及最新的AVX(Advanced Vector Extension)。每个版本的拓展都是管理寄存器组的数据,这些寄存器组在MMX中称为“MM”寄存器,64位;SSE中称为“XMM”寄存器,128位;而在AVX中称为“YMM”寄存器,256位。每个寄存器都可以存放整数或浮点数。

AVX浮点体系结构允许数据存储在16个YMM寄存器中,名字为%ymm0 ~ %ymm15,每个YMM寄存器都是256位,当对标量数据操作时,这些寄存器只保存浮点数,而且只使用低32位(float)或64位(double)。汇编代码用寄存器的SSE XMM寄存器名字%ymm0 ~ %ymm15来引用,每个XMM寄存器都对应的YMM寄存器的低128位。
请添加图片描述

2.2 浮点传送和转换操作

(1)不做转换的浮点数传送指令,包括从内存传送数据到XMM寄存器vmovss,或从XMM寄存器传送数据到内存vmovsd,以及在两个XMM寄存器之间传送数据vmovaps、vmovapd
请添加图片描述
(2)把一个从XMM寄存器或内存中读出的浮点值进行转换,并将结果写入一个通用寄存器。把浮点值转换为整数时,指令会执行截断,把值向0进行舍入。
请添加图片描述

(3)整数转换成浮点数,使用三操作数格式,包括两个源和一个目的。目标必须是XMM寄存器。
请添加图片描述

2.3 过程中的浮点代码

当函数包含指针、整数和浮点数混合的参数时,指针和整数通过通用寄存器传递,而浮点数通过XMM寄存器传递。

  • XMM寄存器%xmm0~%xmm7最多可以传递8个浮点参数,按照参数列表中的顺序使用这些寄存器,额外的浮点参数通过栈传递。
  • 函数使用寄存器%xmm0来返回浮点值。
  • 所有的XMM寄存器都是调用者保存的,被调用者可以不用保存就覆盖这些寄存器中的任意一个。

2.4 浮点运算操作

每条指令有一个或两个源操作数,一个目的操作数,第一个源操作数S1可以是一个XMM寄存器或一个内存位置。第二个源操作数和目的操作数都必须是XMM寄存器,每个操作都有一条针对单精度的指令和一条针对双精度的指令,结果存放在目的寄存器中。
请添加图片描述

2.5 定义和使用浮点常数

和整数运算操作不同,AVX浮点操作不能以立即数值作为操作数。相反,编译器必须为所有的常量值分配和初始化存储空间。然后,代码把这些值从内存读入。以摄氏度到华氏度转换的函数为例说明该过程。

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

相应的x86-64汇编代码部分如下:
请添加图片描述
可以看到,函数从标号为.LC2的内存位置读出1.8,从标号为.LC3的位置读入值32.0。.LC2有两个值:3435973837(0xcccc cccd)和1073532108(0x3ffc cccc)。机器采用的是小端字节顺序,第一个给出的是低位4字节,第二个给出的是高位4字节。所以,符号位和指数字段为0x3ff(1023),减去偏置值(1023)得到指数0,小数字段为0xc cccc cccc cccd,二进制小数表示0.8,加上隐式的1得到常量1.8。

2.6 位级操作

这些操作都作用于封装好的数据,即更新整个目的XMM寄存器,对两个源寄存器的所有位都实施指定的位级操作。
请添加图片描述

2.7 比较操作

类似于CMP指令,浮点比较指令比较操作数,并且设置条件码指示两者的相对值。参数S2必须在XMM寄存器中,而S1可以在XMM寄存器或内存中。
请添加图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值