关于bsr和lzcnt的困惑

时间:2014-09-05 10:21:12

标签: assembly x86 bmi

我对这两个指令都有点困惑。首先让我们在扫描值为0且未定义/ bsr或bitsize / lzcnt结果时丢弃特殊情况 - 这种差异很明显,不属于我的问题。

我们取二进制值0001 1111 1111 1111 1111 1111 1111 1111

根据英特尔的规范,lzcnt的结果为3

根据英特尔的规范,bsr的结果为28

lzcnt计数,bsr返回第0位的索引或距离(即lsb)。

两个指令如何相同?如果CPU上没有可用的BMI,如何将lzcnt模拟为bsr?或者bsr msb的位是0?英特尔规范中的“代码操作”也有所不同,一个是左边的计数或索引,另一个来自右边。

也许有人可以对此有所了解,我没有没有BMI/lzcnt指令的CPU来测试bsr的回退是否与相同的结果一起工作(因为值0的特殊情况从不扫描发生)。

2 个答案:

答案 0 :(得分:9)

LZCNT给出前导零位的数量。 BSR给出最重要的1位的位索引。因此,对于非零情况,它们有效地做同样的事情,除了结果的解释不同。因此,您只需从31中减去BSR结果即可获得与LZCNT相同的行为,即LZCNT == (31 - BSR)

答案 1 :(得分:8)

要明确的是,lzcntbsr没有工作后备。发生的事情是英特尔使用先前的冗余序列rep bsr来编码新的lzcnt指令。对rep使用减量bsr前缀通常被定义为被忽略,但需要注意的是,它可能会在未来的CPU 1 上进行不同的解码。

因此,如果您碰巧在不支持它的CPU上执行lzcnt,它将以bsr执行。当然,这个后备并不是完全有意的,它给出了错误的结果(正如Paul R指出他们看同一位但报告的方式不同):这只是方式的结果新指令已编码,以前的CPU如何处理无意义的rep前缀。因此,对于lzcntbsr来说,世界后备几乎完全不合适。

tzcntbsf的情况更为微妙。它使用相同的编码技巧:tzcnt具有与rep bsf相同的编码,但此处“后备”主要用于,因为tzcnt返回的值与bsf相同{1}}表示除零之外的所有输入。对于零输入,tzcnt返回32,但是bsf使目标未定义。

你甚至不能真正使用这个后备:如果你从来没有零输入你也可以使用bsf,保存一个字节并兼容几十年的CPU,如果你有零输入行为不同。

因此,行为可能更好地归类为琐事而不是后备 ......

1 通常这或多或少都是esoterica,但你可以使用例如rep前缀,它们没有功能效果来延长指令以帮助对齐后续代码而不插入显式nop指示。鉴于“可能在将来以不同方式解码”,在编译可能在未来任何CPU上运行的代码时,这将是危险的。