浮点代码
处理器的浮点体系结构包括多个方面,会影响对浮点数据操作的程序如何被映射到机器上,包括:
1) 如何存储和访问浮点数据。通常是通过某种寄存器方式来完成。
2) 对浮点数据操作的指令。
3) 想函数传递浮点数参数和从函数返回浮点数结构的规则。
4) 函数调用过程保持寄存器的规则——例如,一些寄存器被指定为调用者保存,而其他的被指定为被调用者保存。
AVX浮点体系结构允许数据存储在16个YMM寄存器中,它们的名字为%ymm0~%ymm15。每个YMM寄存器都是256位(32位)。
浮点传送和转换操作
浮点传送和转换操作指令汇总
指令 | 源1 | 源2 | 目的 | 描述 |
---|---|---|---|---|
vmovss | M32 | NULL | X | 传送单精度数 |
vmovss | X | NULL | M32 | 传送单精度数 |
vmovsd | M64 | NULL | X | 传送双精度数 |
vmovsd | X | NULL | M64 | 传送双精度数 |
vmovaps | X | NULL | X | 传送对齐的封装好的单精度数 |
vmovapd | X | NULL | X | 传送对齐的封装好的双精度数 |
vcvttss2si | X/M32 | NULL | R32 | 用截断的方法把单精度数转换成整数 |
vcvttsd2si | X/M64 | NULL | R32 | 用截断的方法把双精度数转换成整数 |
vcvttss2siq | X/M32 | NULL | R64 | 用截断的方法把单精度数转换成四字整数 |
vcvttsd2siq | X/M64 | NULL | R64 | 用截断的方法把双精度数转换成四字整数 |
vcvtsi2ss | M32/R32 | X | X | 把整数转换成单精度数 |
vcvtsi2sd | M32/R32 | X | X | 把整数转换成双精度数 |
vcvtsi2ssq | M64/R64 | X | X | 把四字整数转换成单精度数 |
vcvtsi2sdq | M64/R64 | X | X | 把四字整数转换成双精度数 |
vcvtps2pd | X1 | NULL | X2 | **把X1中两个低位单精度值扩展成X2中的两个双精度值 |
vunpcklps | X1 | X2 | X3 | 交叉放置X1和X2的值存储到X3中 |
过程中的浮点代码
在x86-64中,XMM寄存器用来向函数传递浮点参数,以及从函数返回浮点值。
1) XMM寄存器%xmm0~%xmm7最多可以传递8个浮点参数(额外的可以通过栈传递)。
2) 函数使用寄存器xmm0来返回浮点值。
3) 所有的XMM寄存器都是调用者保存的。被调用者可以不用保存就覆盖这些寄存器中任一个。
浮点运算操作
浮点的运算符和整数的运算符大同小异,需要注意的是AVX浮点操作不能以立即数值作为操作数。
Y86指令集体系结构
Y86指令
首先我们要知道的是Y86指令是不存在的,这是本书的作者受到 IA32指令,也就是“x86”的启发,所假想出来的一种处理器体系结构,与 “x86” 相比,Y86指令集的数据类型、指令和寻址方式都要少一些,字节级编码也比较简单。但是它仍然足够完整,能够写一些简单的处理证书的程序,而设计一个Y86处理器要求我们面对许多处理器设计者同样面临的问题。所以学习Y86处理器的设计是很有必要的。
定义一个指令集体系结构,会包括定义各种状态元素,指令集和它们的编码、一组编程规范和异常处理事件。
指令编码
Y86每条指令的第一个字节有唯一的代码和功能组合,给定这个字节,我们就可以决定所有其他附加字节的长度和含义。这个性质保证了处理器可以无二义性的执行目标程序代码。即使代码嵌入在程序的其它字节中,只要从序列的第一个字节开始处理,我们仍然可以很容易的确定指令序列。反过来,如果不知道一段代码序列的起始位置,我们就不能准确的确定怎样将序列划分为单独的指令。对于试图直接从目标代码字节序列中抽取出机器级程序的反汇编程序和其它一些工具来说,就带来了困难。
关于RISC和CISC
两种不同的指令集,各有利弊,这个在之前的博客中也做过对比,想说明的一点是,人们应该考虑如何把两种指令集做结合,才能把处理器作用发挥的更好。