试图通过 EAX 左移一个变量

Posted

技术标签:

【中文标题】试图通过 EAX 左移一个变量【英文标题】:Trying to shift left by EAX a variable 【发布时间】:2017-07-08 16:03:39 【问题描述】:

如何使用命令shl 将变量移1?

mov one, 1

shl one , eax 

返回错误。

【问题讨论】:

【参考方案1】:

唯一进行可变数量移位的方法是将移位计数放入CL 寄存器(这是 32 位 ECX 寄存器的低 8 位)。这是the only encoding available for any of the shift instructions that takes a register source operand。

所以你需要这样做:

mov DWORD PTR [one], 1      ; initialize variable 'one'
mov ecx, eax                ; copy shift count from EAX into ECX
shl DWORD PTR [one], cl     ; one << cl

请注意,这里只使用了ECX 的低 8 位,但这已经足够了,因为无论如何您不能将 DWORD 大小的值移动超过 32 位!事实上,在除 8088/8086 之外的所有设备上,移位计数都将被屏蔽为 5 位(即模 32),将其限制在 0-31 的范围内,包括 0-31。

另外,我应该提一下,虽然您可以使用内存操作数作为像移位这样的算术指令的来源,但您可能不应该因为它比使用一个寄存器。所以,既然你必须破坏一个寄存器,你可以这样做:

mov  ecx, eax
mov  eax, 1
shl  eax, cl
mov  DWORD PTR [one], eax

【讨论】:

【参考方案2】:

除非您使用BMI2 shifts,否则您只能移位cl。比如:

mov edx, 1
shl edx, cl

由于您将值 1 向左移动,因此还有一条适用的指令:btsbts 可以将任何寄存器作为索引。

xor edx, edx
bts edx, eax

将它与内存目标一起使用时要小心,索引不会以 32 为模减少,因此您可以使用它来(不小心)将其设置为远离基地址。

【讨论】:

memory-destination bts 通常比使用 xor + bts edx, eax 创建掩码要慢,然后使用 or [mem], edx。正是因为这种疯狂的 CISC 行为将源寄存器视为位字符串的索引,所以它解码为很多微指令。

以上是关于试图通过 EAX 左移一个变量的主要内容,如果未能解决你的问题,请参考以下文章

汇编程序如何处理在 2 个寄存器上分隔的值(例如 EDX:EAX)?

arm32位固定指令中怎么容纳32位变量

需要帮助理解此函数中的 movzbl 调用

试图理解这个汇编 x86 代码

x86 - 使用内联汇编设置位

Animate CC HTML5 试图通过调用字符串来更改全局变量