英特尔VEX前缀,L位值不符合docs

时间:2016-09-05 13:02:54

标签: assembly x86 avx machine-code illegal-instruction

英特尔指令集参考为我们提供了添加指令:

0xC4, 0xE1, 0x7B, 0x58, 0xC0

我们可以看到L位被忽略(可以是0或1)。

机器码添加xmm0,xmm0,xmm0 C4 - indicates 3-byte VEX prefix E1 - R = 1; X = 1; B = 1; m-mmmm = 1 (implied 0F escape) 7B - W = 0; vvvv = 1111 (xmm0); L = 0; pp = 11 (implied F2 prefix) 58 - opcode byte C0 - mod-rm byte

void exec(Byte* code, int size)
{
    Byte* buf = (Byte*)VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    memcpy(buf, code, size);

    buf[size] = 0xC3;

    ((void (*)())buf)();

    VirtualFree(buf, 4096, MEM_DECOMMIT);
}

void f()
{
    Byte code[] = { 0xC4, 0xE1, 0x7B, 0x58, 0xC0 };

    exec(code, sizeof(code));
}

我们来测试一下:

Thisworkbook.Sheets("SheetName").Cells(1, Columns.Count).End(xlToLeft).Column

很好,视觉工作室反汇编程序也会识别该指令。

然而,当我将 L位更改为1 (0x7B替换为0x7F)时,反汇编程序无法识别该指令并生成无效指令异常。这是否意味着尽管有英特尔手册,L位必须始终为0?

1 个答案:

答案 0 :(得分:2)

看起来LIG并不意味着L位被忽略; 手册的那部分内容错误。在实践中,它实际上是.LZ.128的同义词,并且意味着L必须为0.

英特尔的insn参考手册(x86第2卷第3.1.1.2节(指令汇总表中的操作码列(带VEX前缀的说明))手册)与观察到的行为相矛盾:

  

如果操作码列中存在VEX.LIG:VEX.L值为   忽略。这通常适用于VEX编码的标量SIMD   浮点指令。

但是,它也与同一手册中的其他文档相矛盾。英特尔的手册偶尔会出现错误。 :(我认为你可以报告英特尔论坛上的错误。

据推测,英特尔改变主意忽略该位,并决定保留标量操作码保留的L = 1编码,但忘记更新文档以了解VEX.LIG在insn编码部分的含义。

他们在insn set参考手册成为正式之前发布未来扩展更新,可能在硬件设计的每个细节最终确定之前。 (目前的future-extensions补充pdf描述了AVX512指令(在KNL中找到),以及一些其他扩展,这些扩展还没有在官方手册中提供,或者可以在任何商用硅AFAIK中获得。)(链接到Intel&# 39; s文档页面,以及标签wiki中的大量其他内容。

来自英特尔的insn参考手册,图2-9 VEX位字段

  

L:矢量长度

     
      
  1. 标量或128位向量
  2.   
  3. 256位向量
  4.   

第2.3.6.2节解释了同样的事情。

请注意,某些BMI1 / 2指令使用VEX编码,L = 0。看起来他们用.Lz表示它:VEX.NDS.LZ.0F38.W0 F2 /rANDN r32a, r32b, r/m32