Assembly 左移位操作期间使用的寄存器

Assembly 左移位操作期间使用的寄存器,assembly,bit-shift,Assembly,Bit Shift,我有一个关于在一些基本操作中使用寄存器的小问题。实际上,我已经研究了在诸如XOR或AND等操作期间生成的汇编代码,这些代码很容易理解。有效地,如果我们考虑A= B& C,这将被翻译成3个步骤: b被移动到%rax %rax=%rax+c %rax被移动到一个 请注意,a、b和c是无符号长变量。如果加法被XOR或or替换,则此转换也可用。无论如何,我已经检查了轮班是否也是这样,我发现了一件奇怪的事情:事实上,a=b这就是shl的工作原理。 英特尔手册2B: 将第一个操作数(目标操作数)中的位向左或

我有一个关于在一些基本操作中使用寄存器的小问题。实际上,我已经研究了在诸如XOR或AND等操作期间生成的汇编代码,这些代码很容易理解。有效地,如果我们考虑A= B& C,这将被翻译成3个步骤:

  • b被移动到%rax
  • %rax=%rax+c
  • %rax被移动到一个

  • 请注意,a、b和c是无符号长变量。如果加法被XOR或or替换,则此转换也可用。无论如何,我已经检查了轮班是否也是这样,我发现了一件奇怪的事情:事实上,a=b这就是
    shl
    的工作原理。
    英特尔手册2B:

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

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


    可变长度移位必须使用
    cl

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

    关于这个问题的解释可以在那里找到

    雷克斯W+D3/4 SHL r/m64,CL将r/m64乘以2,CL倍

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

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


    但事实并非如此,移位量取操作数大小的模,因此任何高位都是完全无关的。因此,它只能读取低8位,而且它也可以,尽管这一决定在16位的日子里可能比现在更有意义(
    ch
    )。较新的
    shrx
    -系列读取“完整”寄存器(与操作数大小一样宽),然后忽略更多位。

    谢谢您的回答。%cl是否包含%rcx的6个最低有效位?
    rcx
    ->完整64位寄存器,
    ecx
    ->完整寄存器的低32位,
    cx
    ->完整寄存器的低16位,
    ch
    ->完整寄存器的高8位,
    cl
    ->降低完整寄存器的8位。有趣的事实:8位和16位移位仍然使用
    0x1F
    (31)屏蔽移位计数,因此它们可以将所有位移出,并将目标寄存器置零,而不考虑之前的内容。@PeterCordes哦,嘿,这很有趣。我没有真正注意到tbh,我从来没有实际使用8位和16位移位。。你认为这是一个很好的理由,还是仅仅是一个“lol,Intel”的东西?x86掩盖了移位计数。请参阅您链接的参考手册的操作部分。这就是@PeterCordes的原因:谢谢你的补充:我宁愿通过引用来解释,但是你的也很有趣。