x86 中的 BEXTR 指令是如何工作的

Posted

技术标签:

【中文标题】x86 中的 BEXTR 指令是如何工作的【英文标题】:How does the BEXTR instruction in x86 work 【发布时间】:2022-01-09 11:50:38 【问题描述】:

正如标题中提到的,我在 x86 程序集上遇到了 BEXTR(位提取)指令,但我似乎无法理解它是如何工作的。

在网上找了一段时间后,我什至发现了一个假定的 C 等效 (src >> start) & ((1 << len) -1),我似乎也无法理解。

谁能向我解释 BEXTR 指令的工作原理?比特是如何提取的?

【问题讨论】:

这个公式几乎说明了它的作用。它从start 开始提取源的length 位。 如果您不理解移位和掩码等价物,也许英特尔手册的位范围表示法会有所帮助:felixcloutier.com/x86/bextr。但实际上你应该学习基本的位操作,比如 2 的幂减一 => 位掩码。有关介绍,请参阅catonmat.net/low-level-bit-hacks。 【参考方案1】:

比特是如何提取的?

我们真的不需要知道这些位是如何提取的,因为这可能因实现而异。我们只需要知道提取了哪些位。

一般来说,位域是位域之前和之后可能被不需要的位包围的连续位集。因此,我们的想法是删除那些不需要的位,并将感兴趣的位域的顺序位移动到右对齐。

C 公式分解成如下组件:

首先,src >> start 将位 start 移动到位位置 0,有效地右对齐感兴趣的位字段。这既将感兴趣的位域移动到正确的右对齐位置,也消除了不感兴趣的较低位(重要性较低的位,即低于所需的位域)。

剩下要做的就是从length 上方去除任何不需要的位。为此,该公式创建了我们所说的掩码。首先,1<<len 通过将 1(2 的最低幂)向左移动来生成 2 的幂。因此,数字看起来像 1 后跟 len 零个数(例如,对于 len=3,然后是 ..001000)。从 2 的幂中减去 1 会得到一个连续 1 的掩码(例如 001000-1=000111),这里的计数为 len 位为 1。该掩码应用于移位结果,以删除不在感兴趣的位字段中的任何不需要的高位(具有较高重要性的位)。


C 中的另一种方法是左移左对齐位域,然后右移右对齐位域。这种移位消除了任何不需要的高位和低位,同时使位域右对齐,因为这是最后一次移位。这种方法还可以提取有符号和无符号位字段,方法是进行右移算术与逻辑运算。

【讨论】:

【参考方案2】:

图片可能会有所帮助。假设起始位为 5,长度为 9。那么如果我们有

Input : 11010010001110101010110011011010 = 0xd23aacda
                          |-------|
                              \
                               \
                                \
                                 v
                               |-------|
Output: 00000000000000000000000101100110 = 0x00000166

所需的位块进入输出的最低有效位,输出的其余位变为 0。

【讨论】:

以上是关于x86 中的 BEXTR 指令是如何工作的的主要内容,如果未能解决你的问题,请参考以下文章

如何:x86 中的 pow(real, real)

为什么math.h中的cos函数比x86 fcos指令快

x86 架构规范

x86汇编如何查看一个地址的值

如何使用 CPUID 指令正确获取 x86 CPU 功能? [复制]

使用 TYPE 指令汇编 MASM x86