为什么TZCNT适用于我的Sandy Bridge处理器?

时间:2017-05-09 21:34:29

标签: assembly x86 x86-64

我正在运行Core i7 3930k,这是Sandy Bridge微体系结构。 执行以下代码(在MSVC19,VS2015下编译)时,结果让我感到惊讶(参见评论):

int wmain(int argc, wchar_t* argv[])
{
    uint64_t r = 0b1110'0000'0000'0000ULL;
    uint64_t tzcnt = _tzcnt_u64(r);
    cout << tzcnt << endl; // prints 13

    int info[4]{};
    __cpuidex(info, 7, 0);
    int ebx = info[1];
    cout << bitset<32>(ebx) << endl; // prints 32 zeros (including the bmi1 bit)

    return 0;
}

反汇编显示tzcnt指令确实从内在函数发出:

    uint64_t r = 0b1110'0000'0000'0000ULL;
00007FF64B44877F 48 C7 45 08 00 E0 00 00 mov         qword ptr [r],0E000h  
    uint64_t tzcnt = _tzcnt_u64(r);
00007FF64B448787 F3 48 0F BC 45 08    tzcnt       rax,qword ptr [r]  
00007FF64B44878D 48 89 45 28          mov         qword ptr [tzcnt],rax  

为什么我没有得到#UD无效的操作码异常,指令正常运行,并且CPU报告它支持上述指令?

这可能是一些奇怪的微码修订版,其中包含指令的实现,但是没有报告对它的支持(以及bmi1中包含的其他内容)?

我还没有检查其余的bmi1说明,但我想知道这种情况有多常见。

1 个答案:

答案 0 :(得分:3)

Sandy Bridge(及更早版本)处理器似乎支持app.js:32946 Uncaught ReferenceError: BarcodesPOSearch is not defined at HTMLButtonElement.<anonymous> (app.js:32946) at HTMLDocument.dispatch (app.js:23180) at HTMLDocument.elemData.handle (app.js:22988) lzcnt的原因是这两个指令都具有向后兼容的编码。

tzcnt

在较旧的处理器上,只会忽略lzcnt eax,eax = rep bsr eax,eax tzcnt eax,eax = rep bsf eax,eax 前缀。

这个好消息太多了 坏消息是两个版本的语义都不同。

rep

当来源&lt;&gt;时,至少lzcnt eax,zero => eax = 32, CF=1, ZF=0 bsr eax,zero => eax = undefined, ZF=1 lzcnt eax,0xFFFFFFFF => eax=0, CF=0, ZF=1 //dest=number of msb leading zeros bsr eax,0xFFFFFFFF => eax=31, ZF=0 //dest = bit index of highest set bit tzcnt eax,zero => eax = 32, CF=1, ZF=0 bsf eax,zero => eax = undefined, ZF=1 tzcnt eax,0xFFFFFFFF => eax=0, CF=0, ZF=1 //dest=number of lsb trailing zeros bsf eax,0xFFFFFFFF => eax=0, ZF=0 //dest = bit index of lowest set bit bsf会生成相同的输出0. tzcntbsr不同意 lzcntlzcnt的执行速度也比tzcnt / bsr快得多 完全糟糕的是bsfbsf无法就标志使用情况达成一致。 这种不必要的不​​一致意味着我不能使用tzcnt作为tzcnt的替代品,除非我能确定其来源是非零的。