为什么汇编指令在“lea”指令中包含乘法?

时间:2012-05-09 08:03:02

标签: assembly x86 disassembly machine-instruction

我正在处理性能至关重要的应用程序的非常低级别的部分。

在调查生成的程序集时,我注意到以下指令:

lea eax,[edx*8+8]

我习惯在使用内存引用时看到添加内容(例如[edx + 4]),但这是我第一次看到乘法。

  • 这是否意味着x86处理器可以在lea指令中执行简单的乘法运算?
  • 这种乘法是否会对执行指令所需的周期数产生影响?
  • 乘法是否限制为2的幂(我会假设是这种情况)?

提前致谢。

3 个答案:

答案 0 :(得分:11)

扩展我的评论并回答问题的其余部分......

是的,它仅限于2的权力。 (具体为2,4和8)因此不需要乘数,因为它只是一个班次。其重点是从索引变量和指针快速生成地址 - 其中数据类型是简单的2字节,4字节或8字节字。 (虽然它也经常被滥用于其他用途。)

至于所需的周期数:根据Agner Fog's tableslea指令在某些机器上是常量,在其他机器上是变量。

在桑迪桥上,如果它是“复杂或撕裂相对”则会有2个周期的惩罚。但它并没有说“复杂”是什么意思......所以除非你做基准测试,否则我们只能猜测。

答案 1 :(得分:8)

实际上,这不是lea指令特有的内容。

这种类型的寻址称为Scaled Addressing Mode。乘法是通过位移实现的,这是微不足道的:

A Left Shift

例如,您可以使用mov执行“缩放寻址”(请注意,这不是相同的操作,唯一的相似之处是ebx*4表示地址乘法):< / p>

 mov edx, [esi+4*ebx]

(来源:http://www.cs.virginia.edu/~evans/cs216/guides/x86.html#memory

有关更完整的商家信息,请参阅this Intel document。表2-3显示允许缩放2,4或8。没别了。

延迟(就循环次数而言):我认为这根本不会受到影响。转换是一个连接问题,在三个可能的转换之间进行选择是1个多路复用器值得延迟的问题。

答案 2 :(得分:6)

扩展您的上一个问题:

  

乘法是否限制为2的幂(我会假设是这种情况)?

请注意,您得到base + scale * index的结果,因此虽然scale必须是1,2,4或8(x86整数数据类型的大小),但您可以得到等效的乘法通过使用与baseindex相同的寄存器,通过一些不同的常量,例如:

lea eax, [eax*4 + eax]   ; multiply by 5

编译器使用它来降低强度,例如:对于乘以100,取决于编译器选项(目标CPU模型,优化选项),您可能会得到:

lea    (%edx,%edx,4),%eax   ; eax = orig_edx * 5
lea    (%eax,%eax,4),%eax   ; eax = eax * 5 = orig_edx * 25
shl    $0x2,%eax            ; eax = eax * 4 = orig_edx * 100