Assembly 左移位操作期间使用的寄存器
我有一个关于在一些基本操作中使用寄存器的小问题。实际上,我已经研究了在诸如XOR或AND等操作期间生成的汇编代码,这些代码很容易理解。有效地,如果我们考虑A= B& C,这将被翻译成3个步骤: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: 将第一个操作数(目标操作数)中的位向左或
请注意,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的原因:谢谢你的补充:我宁愿通过引用来解释,但是你的也很有趣。