指令集与现代x86汇编

在了解现代x86汇编之前,最好有一定的汇编基础,可以看一下两万字汇编学习笔记

CPU指令集

CPU的Code Name、支持的指令集可以在CPU-Z中查看

指令集划分很复杂,看到好几个版本了,所有内容以官方文档和实际情况为准

SIMD指令集
在这里插入图片描述

在这里插入图片描述

SIMD

MMX

Multi Media eXtension,多媒体扩展*指令*集

MMX指令集支持算数、比较、移位等运算,MMX指令集的向量寄存器是64bit

SSE

Streaming SIMD Extensions,单指令多数据流扩展

所有的SSE系列指令的向量寄存器都是128bit

  • SSE

    向量寄存器由MMX的64bit拓展到128bit

  • SSE2

    包括了SIMD的浮点和整型运算的指令以及整型和浮点数据之间的转换

  • SSE3

    支持不对其访问,处理虚数运算的复杂指令以及水平加减操作运算指令

  • SSSE3

  • SSE4.1

    加入了处理字符串文本和面向应用的优化指令

  • SSE4.2

AVX

Advanced Vector Extensions

在之前的SSE128位扩展到和256位的单指令多数据流

  • AVX

    由128bit拓展到256bit,增强了数据重排和灵活的不对齐地址访问

  • AVX2

    增加了256bit的整数向量操作,融合乘加,跨通道数据重排等等

  • AVX-512

    由256bit扩展到512bit

    AVX-512 由多个指令子集组成,并非所有指令子集都被所有实现它们的处理器支持

  • AVX-VNNI、AVX-IFMA

    AVX-VNNI 是AVX512-VNNI指令集扩展的VEX编码变体,AVX-IFMA 是AVX512-IFMA的VEX编码变体

  • AVX10

    于 2023 年 8 月发布,强制支持512位向量

Intel IMCI

向量寄存器长度扩展到512bit

VT-x

虚拟化

EM64T

扩展64bit内存技术

FMA

Fused-Multiply-Add,积和熔加运算,又叫乘积累加运算

实际上是用一个指令把加减法和乘法结合在一起,提高处理速度

现代x86汇编

现代CPU加入了许多SIMD指令以提高性能,而现代汇编正与此对应。

现代x86汇编中的多数指令,同时支持多个指令集,如vmovups既可以被用来执行vmovups xmm0, xmmword ptr [rcx]又可以用来执行vmovups ymm0, ymmword ptr [rcx]vmovups zmm0, zmmword ptr [rcx]

x64调用规约

关于调用规约,详见x64调用约定; 关于寄存器使用,详见x64 ABI约定:x64寄存器使用情况

  • 前四个浮点参数值通过寄存器XMM0、XMM1、XMM2和XMM3传递给函数,这四个寄存器是易失的
  • 浮点返回值在XMM0中
  • 浮点值不能作为立即数参数

叶函数是包含以下特点的函数

  • 不会调用任何其它函数
  • 不会修改RSP寄存器内容
  • 不会分配任何局部堆栈空间
  • 不会修改任何非易失性寄存器或者XMM寄存器
  • 不会使用异常处理

个人对于叶函数的理解:把程序以树的形式呈现,一个函数是一个结点,那么这类没有进一步调用的基础函数就是叶函数

; 非叶函数示例
; extern "C" framePointerExample(void)
framePointerExample proc frame
	; prologue
	push rbp			; 保存非易失性寄存器
	.pushreg rbp
	sub rsp, 16			; 在堆栈上为局部变量分配空间
	.allocstack 16
	mov rbp, rsp		; 设置堆栈帧指针
	.setframe rbp, 0
	.endprolog			; 8 + 16 = 24



	; epilogue
	add rsp, 16			; 恢复RSP寄存器
	pop rbp				; 还原非易失性寄存器
	ret
framePointerExample endp

AVX指令集

环绕与饱和运算:环绕算术运算中,数据可能会在运算过程中溢出,而此时在饱和算术运算中,结果会被裁剪为可以装载的最大值

x86-AVX和x86-SSE之间的区别

AVX执行环境

寄存器集

支持AVX的x86-64处理器包含16个256位大小的寄存器,名为YMM0~YMM15。每个YMM寄存器的低阶128位的别名是相对应的XMM寄存器。早期指令集扩展和x86-AVX之间存在一些细微的执行差异。

x86-AVX执行环境还包括一个名为MXCSR的控制状态寄存器,检测浮点运算引起的错误情况。

指令语法

大多数x86-AVX指令使用一个三操作数格式,即包括两个源操作数和一个目标操作数。x86-AVX指令采用的一般语法格式为InstrMnemonic DesOp, SrcOp1, SrcOp2,其中InstrMnemonic表示指令助记符,DesOp表示目标操作数,SrcOp表示源操作数。一小部分x86-AVX指令集适用一个或者三个源操作数和一个目标操作数。

几乎所有的x86-AVX指令源操作数都是非破坏性的。 这意味着在指令执行期间不会修改源操作数,除非目标操作数寄存器与其中一个源操作数寄存器相同。

使用非破坏性源操作数通常会导致代码更简单、执行速度更快,因为函数必须执行的寄存器到寄存器的数据传输数量有所减少

AVX标量浮点数

控制状态寄存器

寄存器占32位,从低位到高位,依次是IE、DE、ZE、OE、UE、PE、DAZ、IM、DM、ZM、OM、UM、PM、RC、FTZ,剩余16位为保留字段。

在这里插入图片描述

应用程序可以修改MXCSR的任何控制标志或者状态位,以适应其特定的SIMD浮点处理要求。

MXCSR寄存器的控制标志和状态位可以使用vldmxcsr(加载MXCSR寄存器)指令修改。

将掩码位设置为1将禁用相应的异常

vstmxcsr(存储MXCSR寄存器)指令可以用于保存当前MXCSR状态。

应用程序无法直接访问指定浮点异常处理程序的内部处理表。大多数C++编译器提供了库函数,当发生浮点异常时,允许程序指定调用的回调函数。

MXCSR包含两个控制标志,可以用于加速某些浮点运算。(不符合IEEE 754浮点数标准

  • 把MXCSR.DAZ控制标志设置为1,可以提高非规范化值舍入为零的算法性能
  • MXCSR.FTZ常用于加速浮点向下溢出的计算

任何试图将非零值写入保留位位置的尝试都将导致处理器产生异常

出现错误后,处理器将MXCSR错误标志设置为1。

检测到错误后,处理器不会自动清除MXCSR错误标志,必须手动重置这些标志


指令集

[d|s]表示指令既可以用于双精度浮点操作数,也可以用于单精度浮点操作数

助记符说明
vadds[d|s]标量浮点值加法
vbroadcasts[d|s]广播标量浮点值
vcmps[d|s]标量浮点值比较
vcomis[d|s]有序标量浮点值比较并设置RFLAGS
vcvts[d|s]2si把标量浮点值转换为双字有符号整数
vcvtsd2ss把标量DPFP转换为标量SPFP
vcvtsi2s[d|s]把有符号双字整数转换为标量浮点值
vcvtss2sd把标量SPFP转换为DPFP
vcvtts[d|s]2si以截断方式把标量浮点值转换为有符号整数
vdivs[d|s]标量浮点值除法
vmaxs[d|s]标量浮点值最大值
vmins[d|s]标量浮点值最小值
vmovs[d|s]移动标量浮点值
vmuls[d|s]标量浮点值乘法
vrounds[d|s]四舍五入标量浮点值
vsqrts[d|s]标量浮点值平方根
vsubs[d|s]标量浮点值减法
vucomis[d|s]无序标量浮点值比较并设置RFLAGS

vcmps[d|s]与vcomis[d|s]和vucomis[d|s]的区别是vcmps[d|s]是四操作数的,返回双字掩码,且需要用到比较谓词

; e.g.
vcmpss xmm2, xmm0, xmm1, CMP_EQ

option casemap:none
;-------------------------------
;			比较谓词
;-------------------------------
; 基本比较谓词
CMP_EQ			equ 00h
CMP_LT			equ 01h
CMP_LE			equ 02h
CMP_UNORD		equ 03h
CMP_NEQ			equ 04h
CMP_NLT			equ 05h
CMP_NLE			equ 06h
CMP_ORD			equ 07h
; AVX的扩展比较谓词
CMP_EQU_UQ		equ 08h
CMP_NGE			equ 09h
CMP_NGT			equ 0Ah
CMP_FALSE		equ 0Bh
CMP_NEQ_OQ		equ 0Ch
CMP_GE			equ 0Dh
CMP_GT			equ 0Eh
CMP_TRUE		equ 0Fh
CMP_EQ_OS		equ 10h
CMP_LT_OQ		equ 11h
CMP_LE_OQ		equ 12h
CMP_UNORD_S		equ 13h
CMP_NEQ_US		equ 14h
CMP_NLT_UQ		equ 15h
CMP_NLE_UQ		equ 16h
CMP_ORD_S		equ 17h
CMP_EQ_US		equ 18h
CMP_NGE_UQ		equ 19h
CMP_NGT_UQ		equ 1Ah
CMP_FLASE_OS	equ 1Bh
CMP_NEQ_OS		equ 1Ch
CMP_GE_OQ		equ 1Dh
CMP_GT_OQ		equ 1Eh
CMP_TRUE_US		equ 1Fh

AVX打包浮点值

指令集
指令描述
vaddp[d|s]打包浮点值加法
vaddsubp[d|s]打包浮点值加减法
vandp[d|s]打包浮点值按位与
vandnp[d|s]打包浮点值按位与非
vblendp[d|s]打包浮点值混合运算
vblendvp[d|s]可变打包浮点值混合运算
vcmpp[d|s]打包浮点值比较
vcvtdq2p[d|s]打包有符号双字转换为浮点值
vcvtp[d|s]2dq打包浮点值转换为有符号双字
vcv2pd2ps打包DPFP转换为打包SPFP
vcvtpd2ps打包SPFP转换为打包DPFP
vdivp[d|s]打包浮点值除法
vdpp[d|s]打包浮点值点积
vhaddp[d|s]水平打包浮点值加法
vhsubp[d|s]水平打包浮点值减法
vmaskmovp[d|s]打包浮点值载入和存储
vmaxp[d|s]打包浮点值最大值
vminp[d|s]打包浮点值最小值
vmovap[d|s]移动对齐的打包浮点值
vmovskp[d|s]提取打包浮点值符号位掩码
vmovup[d|s]移动未对齐的打包浮点值
vmulp[d|s]打包浮点值乘法
vorp[d|s]打包浮点值按位兼或
vpermilp[d|s]按通道排列打包浮点值元素
vroundp[d|s]四舍五入打包浮点值
vshufp[d|s]混洗打包浮点值
vsqrtp[d|s]打包浮点值平方根
vsubp[d|s]打包浮点值减法
vunpckhp[d|s]解包并交叉高位打包浮点值
vunpcklp[d|s]解包并交叉低位打包浮点值
vxorp[d|s]打包浮点值按位异或
  • __m128这种变量,它们的定义为typedef union __declspec(intrin_type) __declspec(align(16)) __m128,也就是已经对齐过了,直接使用vmovap[d|s]即可

  • 打包浮点数的比较,是两个向量的同一位置互相比较,为真则全1,为否则全0

  • 打包浮点数的最大/最小值,是两个向量的同一位置互相比较,返回同一位置上的最大/最小值

  • 解包并交叉低位打包浮点值(高位与之相似):

    • xmm0: a 3 a 2 a 1 a 0 a_3\quad a_2\quad a_1\quad a_0 a3a2a1a0

    • xmm1: b 3 b 2 b 1 b 0 b_3\quad b_2\quad b_1\quad b_0 b3b2b1b0

    • vunpcklps xmm2, xmm0, xmm1
      
    • xmm2: b 1 a 1 b 0 a 0 b_1\quad a_1\quad b_0\quad a_0 b1a1b0a0

  • 利用交叉将浮点矩阵转置

    ; void spfp4x4Transpose(__m128& a, __m128&b, __m128&c, __m128&d)
    spfp4x4Transpose proc
    	sub rsp, 48
    	vmovups xmmword ptr [rsp-16], xmm4
    	vmovups xmmword ptr [rsp-32], xmm5
    	vmovups xmmword ptr [rsp-48], xmm6
    	vmovaps xmm0, xmmword ptr [rcx]	; xmm0 = a3 a2 a1 a0
    	vmovaps xmm1, xmmword ptr [rdx]	; xmm1 = b3 b2 b1 b0
    	vmovaps xmm2, xmmword ptr [r8]	; xmm2 = c3 c2 c1 c0
    	vmovaps xmm3, xmmword ptr [r9]	; xmm3 = d3 d2 d1 d0
    	
    	vunpcklps xmm4, xmm0, xmm1		; xmm4 = b1 a1 b0 a0
    	vunpcklps xmm5, xmm2, xmm3		; xmm5 = d1 c1 d0 c0
    	vmovlhps xmm6, xmm4, xmm5		; xmm6 = d0 c0 b0 a0
    	vmovaps xmmword ptr [rcx], xmm6
    	vmovhlps xmm6, xmm4, xmm5		; xmm6 = d1 c1 b1 a1
    	vmovaps xmmword ptr [rdx], xmm6
    	vunpckhps xmm0, xmm0, xmm1		; xmm0 = b3 a3 b2 a2
    	vunpckhps xmm1, xmm2, xmm3		; xmm1 = d3 c3 d2 c2
    	vmovlhps xmm4, xmm0, xmm1		; xmm4 = d2 c2 b2 a2
    	vmovaps xmmword ptr [r8], xmm4
    	vmovhlps xmm5, xmm1, xmm0		; xmm5 = d3 c3 b2 a2
    	vmovaps xmmword ptr [r9], xmm5
    
    	vmovups xmm6, xmmword ptr [rsp-48]
    	vmovups xmm5, xmmword ptr [rsp-32]
    	vmovups xmm4, xmmword ptr [rsp-16]
    	add rsp, 48
    	ret
    spfp4x4Transpose endp
    

AVX打包整数

指令集
指令描述
vmov[d|q]移动到/移动出XMM寄存器
vmovdqa移动对齐的打包整数值
vmovdqu移动非对齐的打包整数值
vpabs[b|w|d]打包整数绝对值
vpackss[dw|wb]有符号饱和的打包
vpackus[dw|wb]无符号饱和的打包
vpadd[b|w]打包整数加法
vpadds[b|w]有符号饱和的打包整数加法
vpaddus[b|w]无符号饱和的打包整数加法
vpand打包整数按位与
vpandn打包整数按位与非
vpcmpeq[b|w|d|q]打包整数比较相等性
vpcmpgt[b|w|d|q]打包整数比较大于
vpextr[b|w|d|q]从XMM寄存器提取整数
vphadd[w|d]水平打包加法
vphsub[w|d]水平打包减法
vpinsr[b|w|d|q]将整数插入XMM寄存器
vpmaxs[b|w|d]打包有符号整数最大值
vpmaxu[b|w|d]打包无符号整数最大值
vpmins[b|w|d]打包有符号整数最小值
vpminu[b|w|d]打包无符号整数最小值
vpmovsx带符号扩展的打包整数移动
vpmovzx零扩展的打包整数移动
vpmuldq打包有符号双字乘法
vpmulhuw打包无符号双字乘法,保存高位结果
vpmul[h|l]w打包有符号字乘法,保存[高位|低位]结果
vpmull[d|w]打包有符号字乘法,保存低位结果
vpmuludq打包无符号字乘法
vpshuf[b|d]混洗打包整数
vpshuf[h|l]w混洗[高位|低位]打包整数
vpslldq双四字逻辑左移
vpsll[w|d|q]打包逻辑左移
vpsra[w|d]打包算术右移
vpsrldq双四字逻辑右移
vpsrl[w|d|q]打包逻辑右移
vpsub[b|w|d|q]打包整数减法
vpsubs[b|w]有符号饱和的打包整数减法
vpsubus[b|w]无符号饱和的打包整数减法
vpunpckh[bw|wd|dq]解包高位数据
vpunpckl[bw|wd|dq]解包低位数据

AVX2

x86指令集扩展

助记符说明
vbroadcasti128广播128位整数数据
vextracti128提取128位整数数据
vinserti128插入128位整数数据
vpblendd混合打包双字
vpbroadcast[b|w|d|q]广播整数值
vperm2i128排列128位整数数据
vperm[d|q]排列打包整数
vpgatherd[d|q]使用有符号双字索引的打包整数收集
vpgatherq[d|q]使用有符号四字索引的打包整数收集
vpmaskmov[d|q]条件打包整数移动
vpsllv[d|q]使用单独元素计数的逻辑左移位
vpsravd使用单独元素计数的算术右移位
vpsrlv[d|q]使用单独元素计数的逻辑右移位
指令集扩展CPUID功能标志
扩展无符号整数加法ADX
高级位操作(组1)BMI1
高级位操作(组2)BMI2
半精度浮点转换F16C
乘法加法融合FMA
计数前导零位LZCNT
计数设置位POPCNT
半精度浮点数
助记符说明
vcvtph2ps把半精度浮点数转换为单精度浮点数
vcvtps2ph把单精度浮点数转换为半精度浮点数
FMA(积和熔加运算)

在这里插入图片描述

通用寄存器指令集扩展

AVX-512

其实和AVX、AVX2差不多,指令几乎没什么变化,只是提供了更高的吞吐量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值