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

Pat*_*ick 11 x86 assembly disassembly machine-instruction

我正在开发一个非常低级别的应用程序,其中性能至关重要.

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

lea eax,[edx*8+8]
Run Code Online (Sandbox Code Playgroud)

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

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

提前致谢.

Mys*_*ial 11

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

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

至于所需的循环次数:根据Agner Fog的表格,看起来lea指令在某些机器上是恒定的而在其他机器上是变量的.

在Sandy Bridge,如果它是"复杂或裂口相对"则会有2个周期的惩罚.但它并没有说"复杂"是什么意思......所以除非你做基准测试,否则我们只能猜测.

  • 注意,虽然技术上乘法是1,2,4或8,但如果你也考虑基址寄存器你可以得到其他常数的乘法,例如:`lea eax,[edx*4 + edx]`相当于乘法这对于强度降低非常有用,例如:编译器可以生成一些乘以1000的智能代码. (4认同)
  • 复合意味着3个操作数或移位> 1. (2认同)

Arj*_*kar 8

实际上,这不是lea指令的具体内容.

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

左移

例如,您也可以使用"缩放寻址" mov(请注意,这不是相同的操作,唯一的相似之处是ebx*4代表地址乘法的事实):

 mov edx, [esi+4*ebx]
Run Code Online (Sandbox Code Playgroud)

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

有关更完整的列表,请参阅此英特尔文档.表2-3显示允许缩放2,4或8.没有其他的.

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


nin*_*alj 6

要扩展您的上一个问题:

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

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

lea eax, [eax*4 + eax]   ; multiply by 5
Run Code Online (Sandbox Code Playgroud)

编译器使用它来降低强度,例如:对于乘以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
Run Code Online (Sandbox Code Playgroud)

  • 请参阅此问题:http://stackoverflow.com/questions/6120207/imul-or-shift-instruction,了解为什么应将强度降低留给编译器。 (2认同)