【问题标题】:Registers used during left shift operation左移操作期间使用的寄存器
【发布时间】:2016-09-27 08:46:39
【问题描述】:

我有一个关于在一些基本操作中使用寄存器的小问题。实际上,我已经查看了在 XOR 或 AND 等操作期间生成的汇编代码,这些代码很容易理解。实际上,如果我们考虑 a = b & c,这将分为 3 个步骤:

  1. b 被移动到 %rax
  2. %rax = %rax + c
  3. %rax 被移动到一个

请注意,a、b 和 c 是无符号长变量。如果将加法替换为 XOR 或 OR,则此转换也可用。无论如何,我检查过轮班是否也是这种情况,我发现一个奇怪的事情:事实上,a = b

  1. b 被移动到 %rax
  2. c 被移动到 %rcx
  3. %rax = %rax
  4. %rax 被移动到一个

我不太确定我是否真的了解第二步和第三步。我想这是因为 %rax (b) 不能移动超过 63 位,否则结果显然是 0。似乎 %cl 是一个 8 位寄存器,所以我认为这是一种快速的方法只选择有用的位而不是 %rcx 中的 64 位。对吗?

谢谢

【问题讨论】:

    标签: assembly x86 x86-64 bit-shift


    【解决方案1】:

    这就是shl 的工作原理。
    来自英特尔手册 2B:

    将第一个操作数(目标操作数)中的位向左或向右移动指定的位数 第二个操作数(计数操作数)。移出目标操作数边界的位首先移入 CF 标志,然后丢弃。在移位操作结束时,CF 标志包含移出目标的最后一位 操作数。

    目标操作数可以是寄存器或内存位置。 计数操作数可以是立即数或 CL 寄存器。计数被屏蔽为 5 位(如果在 64 位模式下使用 REX.W,则为 6 位)。计数范围为 限制为 0 到 31(如果使用 64 位模式和 REX.W,则为 63)。为计数 1 提供了特殊的操作码编码。

    可变长度移位必须使用cl

    【讨论】:

    • 感谢您的回答。 %cl 是否包含 %rcx 的 6 个最低有效位?
    • rcx -> 完整的 64 位寄存器,ecx -> 完整寄存器的低 32 位,cx -> 完整寄存器的低 16 位,ch -> 上cxcl 的 8 位 -> 全寄存器的低 8 位。
    【解决方案2】:

    我想这是因为%rax(b)不能移动超过63,否则结果显然是0。

    如果它像那样工作,它可能会使用rcx 作为操作数(或者在任何上下文中最有意义的宽度,即指令的操作数大小),以检查是否设置了任何高位(并将结果设置为零(如果有)。

    但它没有,移位量取模操作数大小,所以任何高位都是完全不相关的。所以它可以只读取低 8 位,而且它也可以,尽管这个决定在 16 位时代(实际上会使用ch)可能比现在更有意义。较新的shrx-family 读取“完整”寄存器(与操作数大小一样宽),然后忽略更多位。

    【讨论】:

    • 有趣的事实:8 位和 16 位移位仍然用 0x1F (31) 掩盖移位计数,因此它们可以将所有位移出并将目标寄存器保持为零以前的内容。
    • @PeterCordes 哦,嘿,这很有趣。我并没有真正注意到 tbh,我从来没有真正使用过 8 和 16 位移位。你认为这是有充分的理由还是只是其他“大声笑,英特尔”的事情?
    • 刚才又碰巧看到了:当他们在 186 中引入掩码时,一些现有的 8086 代码可能依赖于能够移出所有位(16 位寄存器,这是8086 中存在的最宽的)。但是在 386 中加宽寄存器时,掩码已被定义为 ISA 的一部分,因此它们可以使桶形移位器保持更窄。这就是我关于动机是什么的理论。 (就像我在Why any modern x86 masks shift count to the 5 low bits in CL 中写的那样)
    【解决方案3】:

    嗯,CL 是一个 8 位寄存器,可能的值为 0..255。所以将一些值移动到%RCX 只是部分相关,因为只有最低的 8 位 (CL) 会计算在内。像%RAX 这样的 64 位目标寄存器只能左移 63 位而不会溢出。将其向左移动 64 位或更多位(最多 255 = CL 的最大值)将始终导致 0(零)。所以你的假设是正确的。

    可以在此处找到relevant SHL OpCode 的解释。

    REX.W + D3 /4     SHL r/m64, CL     r/m64 乘以 2,CL 次。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-05
    相关资源
    最近更新 更多