我对一些基本操作中寄存器的使用有一个小问题。实际上,我已经查看了在XOR或AND等操作过程中产生的汇编代码,这些代码很容易理解。实际上,如果我们考虑a = b& c,这将分为3个步骤:
请注意,a,b和c是无符号长变量。如果添加被XOR或OR替换,也可以使用此转换。无论如何,我已经检查过是否也是轮班的情况,我发现了一个奇怪的事情:事实上,a = b<< c翻译如下
我不太确定我真的理解第二步和第三步。我想这是因为%rax(b)不能移位超过63,否则,结果显然为0.看来%cl是一个8位寄存器,所以我认为这是一种快速的方式只选择%rcx中的有用位而不是64位。这是对的吗?
谢谢
答案 0 :(得分:3)
我想这是因为%rax(b)不能移动超过63,否则结果显然为0.
如果它像那样工作,它可能会使用rcx
作为操作数(或者在任何上下文中使用宽度最有意义,即指令的操作数大小),以检查是否有任何高位set(如果设置了任何设置,则将结果设置为零)。
但事实并非如此,移位量取决于操作数大小,因此任何高位都完全无关紧要。所以它可以只读低8位,它也可以,但是这个决定可能在16位日内更有意义(ch
实际上会被使用)比现在更有意义。较新的shrx
- 系列读取“完整”寄存器(与操作数大小一样宽),然后忽略更多位。
答案 1 :(得分:2)
这就是shl
的工作原理
来自英特尔手册2B:
将第一个操作数(目标操作数)中的位向左或向右移动指定的位数。 第二个操作数(计数操作数)。移位到目标操作数边界之外的位首先移入CF. 标志,然后丢弃。在移位操作结束时,CF标志包含从目标移出的最后一位 操作数。
目标操作数可以是寄存器或内存位置。 计数操作数可以是立即值或 CL寄存器。计数被屏蔽为5位(如果在64位模式下使用REX.W则为6位)。计数范围是 限制为0到31(如果使用64位模式和REX.W,则为63)。计数为1的特殊操作码编码。
可变长度转换必须使用cl
。
答案 2 :(得分:1)
嗯,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次。