我对这两个指令都有点困惑.首先,让我们丢弃的特殊情况下,当扫描的值是0和未定义/ BSR或bitsize/lzcnt结果 - 这种差异是明显的,而不是我的问题的一部分.
我们来看二进制值 0001 1111 1111 1111 1111 1111 1111 1111
根据英特尔的规格,结果为lzcnt3
根据英特尔的规格,结果为bsr28
lzcntcount,bsr从位0返回索引或距离(即lsb).
两个指令如何相同,如何在CPU上没有可用的BMI的情况下lzcnt进行仿真bsr?或者bsr在msb的情况下是0位?英特尔规范中的"代码操作"也不同,一个是左边的计数或索引,另一个来自右边.
也许有人可以提供一些线索这光,我没有CPU无BMI/lzcnt指令测试,如果退回到bsr同样的结果作品(如值为0的特殊情况下扫描从未发生过).
Pau*_*l R 11
LZCNT给出前导零位的数量.BSR给出最重要的1位的位索引.因此,对于非零情况,它们有效地做同样的事情,除了结果的解释不同.因此,您可以BSR从31中减去结果,以获得与之相同的行为LZCNT,即LZCNT == (31 - BSR).
Bee*_*ope 11
需要明确的是,没有工作的后备从lzcnt到bsr.发生的事情是英特尔使用先前的冗余序列rep bsr来编码新lzcnt指令.使用redudant rep前缀bsr通常被定义为被忽略,但需要注意的是它可能在未来的CPU 1上以不同方式解码.
因此,如果您碰巧lzcnt在不支持它的CPU上执行,它将执行为bsr.当然,这种回退并不是完全有意的,它给出了错误的结果(正如Paul R指出他们看同一位但报告的方式不同):这只是新指令编码方式和无意义的结果rep前缀由先前的CPU处理.因此,世界后备几乎完全不适合lzcnt和bsr.
这种情况对的情况下,更微妙tzcnt和bsf.它使用相同的编码技巧:tzcnt具有相同的编码rep bsf,但这里"回退" 主要起作用,因为tzcnt返回与bsf除零之外的所有输入相同的值.对于零输入,tzcnt返回32,但bsf使目标未定义.
你甚至不能真正使用这个后备:如果你从来没有零输入你也可以使用bsf,保存一个字节并兼容几十年的CPU,如果你没有输入,行为就会有所不同.
所以这种行为可能更好地被归类为琐事而不是后备 ......
1通常情况下,这或多或少都是esoterica,但是你可以使用rep前缀,它们没有功能效果来延长指令以帮助对齐后续代码而不插入显式nop指令.鉴于"将来可能会有不同的解码",在编译可能在未来的CPU上运行的代码时,这将是危险的.