前言
这篇文章只是分析AVX512的前缀,关于REX前缀和VEX前缀的一些信息,会放到后面的附录节里。当然,要理解AVX512前缀的前提条件,是要先熟悉REX前缀和VEX前缀。为了保证文章的简洁和方便查阅,此文章将采用图表展示加指令示例来解释字节前缀。其他冗余但必要的信息将会放到后面的附录章节,并会给出在Intel手册的具体位置。
简介
AVX 指令集是高级矢量扩展(Advanced Vector Extensions)的缩写。在2013年,Intel发布了AVX512。AVX512是AVX的第二代,其指令宽度由AVX的256位扩展至512位。
AVX512新增加和扩展了ZMM0-ZMM31、XMM16-XMM31、YMM16-YMM31矢量寄存器,以及8个掩码寄存器(k0-k7)。(图表信息查看附录的EVEX前缀那节)
AVX512前缀叫做EVEX前缀,由4个字节构成,第1个字节固定为0x62。见图2-11。
关于图2-11的详细释义,在Table 2-30这张表中。(图表信息查看附录的EVEX前缀那节)
下面直接以图表的方式介绍P0、P1、P2。
P0
VADDPD 指令举例
比如指令,VADDPD zmm11 {k1}{z}, zmm2, zmm3
其机器码为: 62 71 ED C9 58 DB
P0
为0x71,分解为下面的位
EVEX.R = 0b
EVEX.X = 1b
EVEX.B = 1b
EVEX.R' = 1b
EVEX.mm = 01b
EVEX.R为0,ymm11寄存器满足表Table 2-1的条件,取反为0。
具有OF的属性,所以EVEX.mm 为 01b。
假如,第三个操作数为zmm17,那么EVEX.X = 0b。P0
为0x31。
VADDPD zmm11 {k1}{z}, zmm2, zmm17 -> 机器码 62 31 ED C9 58 D9
假如,第三个操作数为zmm25,那么EVEX.X = 0b,且EVEX.B=0b。此时,P0
为0x11。
VADDPD zmm11 {k1}{z}, zmm2, zmm25 -> 机器码 62 11 ED C9 58 D9
P1
VADDPD 指令举例
比如指令,VADDPD zmm11 {k1}{z}, zmm2, zmm3
其机器码为: 62 71 ED C9 58 DB
P1
为0xED,分解为下面的位
EVEX.W = 1b
EVEX.vvvv = 1101b
EVEX.pp = 01b
EVEX.W的属性为W1,其值为1b。
第二个源向量寄存器操作数是zmm2,查表Table 2-8,可知EVEX.vvvv值为1101b。
EVEX.pp的属性是 66 ,其值为 01b。
P2
VADDPD 指令举例
比如指令,VADDPD zmm11 {k1}{z}, zmm2, zmm3
其机器码为: 62 71 ED C9 58 DB
P2
为0xC9,分解为下面的位
EVEX.z = 1b
EVEX.L'L = 10b
EVEX.b = 0b
EVEX.v' = 1b
EVEX.aaa = 001b
指令中存在{z},所以EVEX.z值为1b,表示对目的操作数所选择的屏蔽操作清零 (而合并行为则是默认的,无需指定修饰符)。
矢量长度是512,EVEX.L'L值为10b。
第二个源向量寄存器操作数是zmm2,EVEX.v'值为1b。
指令中存在{k1},EVEX.aaa 值为001b。
假如,在指令后面加入 {rn-sae},变为VADDPD zmm11 {k1}{z}, zmm2, zmm3 {rn-sae}。
此时,EVEX.L'L = 00b,EVEX.b = 1b,其余不变。则机器码为:62 71 ED 99
58 DB
VISB
VGATHERDPD 指令举例
比如指令,VGATHERDPD zmm18 {k1}, [r11d+ymm25*4] (注意:掩码寄存器必须是k1- k7,如果是K0,将会产生#UD异常)。
机器码为:67 62 82 FD 41 92 14 8B
在EVEX前缀的前面,还有前缀0x67。原因:64位模式下使用了32位的基寄存器(base register),需要加上前缀0x67。
P0
-> 0x82 分解为下面的位
EXEV.R = 1b
EXEV.X = 0b (VSIB.vdix在VR8-VR15或者VR24-VR31,其值取反为0)
EXEV.B = 0b (VSIB.base为r11d,值取反为0)
EXEV.R' = 0b (ModR/M.reg为zmm18,值取反为0)
EXEV.mm=10b (隐含 0F38 操作码)
P1
-> 0xFD 分解为下面的位
EXEV.W =1b (W1 = 1)
EXEV.vvvv =1111b (没有第二个源向量寄存器操作数,默认为1111b,否则产生#UD异常)
EXEV.pp =01b (66 = 01)
P2
-> 0x41 分解为下面的位
EXEV.z=0b
EXEV.L'L=10b (512-bit vector)
EXEV.b =0b
EXEV.v' =0b (VSIB.vdix是ymm25,值取反为0)
EXEV.aaa =001b (存在掩码寄存器k1)
操作码为0x92
0x14转为二进制 0001 0100。 拆分组合 => 00b(Mod) 010b(reg) 100b(rm)。
解析:vsib字段中没有移位(displacement), Mod的值即为00b。reg是zmm18,18 % 8 = 2,即010b。存在vsib字段,rm=100b。
0x8B转为二进制 1000 1011。 拆分组合 => 10b(SS) 001b(index) 011b(base)。
解析:scaled是4,查表Table 2-13,得到SS=10b。index是ymm25,25 % 8 = 1,即001b。base是r11d,11 % 8 = 011b。
特殊情况
假设,vsib中不存在基寄存器(base register),Intel规定了base的默认值为101b,且需要加上一个32位的移位(disp32)。
比如指令,VGATHERDPD zmm18 {k1}, [ymm25*4]
对应的机器码码为: 62 A2
FD 41 92 14 8D 00 00 00 00
如果,base本身就是ebp或者r13d,其映射值为101b,Intel规定了后面必须强制加上移位,但是这样也会导致mod的值发生改变。
比如指令,VGATHERDPD zmm18 {k1}, [r13d+ymm25*4]
对应的机器码为:67 62 82 FD 41 92 54
8D 00
0x54转为二进制 0101 0100。拆分组合 => 01
b(Mod) 010b(reg) 100b(rm)。后面加了一个8位的移位(disp8),所以mod值为01b。
特殊情况2
① 在base和vidx都存在的情况下,如果有移位(disp)值,且disp在[-400h - 3F8h]之间,当disp % 8 = 0时,有disp等于disp / 8。
② 如果存在移位(disp)值,且disp % 8 != 0,那么,disp长度始终是4字节。
情况①举例,比如指令:vgatherdpd zmm18 {k1}, [r13d+ymm25*4-0x400]
对应的机器码为:67 62 82 FD 41 92 94
8D 00 FC FF FF
(-400h -> 32位取反加1为 FFFFFC00h)
上面指令满足条件①,所以有disp = 400h / 8 ,即disp=80h,再取反加1,结果disp=80h。
那么,对应的机器码也可以为:67 62 82 FD 41 92 54
8D 80
附录
REX前缀
更多信息,参看Intel手册第二卷(2A) (43页)
VEX前缀
更多信息,请参看Intel手册第二卷(2A) 49页,107页
EVEX前缀
扩展和增加的寄存器,如下图
以下Table 2-30是Figure 2-11的详细释义
更多信息,请参看Intel手册第二卷(2A) 71页,108页
参考
https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
Intel®AVX512-FP16 Architecture Specification
Intel AVX-512 Brief Introduction: Intel AVX-512简介 (gitee.com)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2023-4-27 00:26
被舒默哦编辑
,原因: