x86 LEA 指令做不明确的事情

Ka *_*koi 1 c assembly x86-64 instruction-set

这是 C 代码:

int baz(int a, int b)
{
    return a * 11;
}
Run Code Online (Sandbox Code Playgroud)

它被编译为以下一组汇编指令(带有 -O2 标志):

baz(int, int):
        lea     eax, [rdi+rdi*4]
        lea     eax, [rdi+rax*2]
        ret
Run Code Online (Sandbox Code Playgroud)

lea指令计算第二个操作数(源操作数)的有效地址并将其存储在第一个操作数中。对我来说,第一条指令似乎应该将地址加载到 EAX 寄存器,但是,如果是这样,在第二条指令中将 RAX 乘以 2 没有意义lea,所以我推断这两lea条指令不会做完全相同的事情。

我想知道是否有人可以澄清这里到底发生了什么。

use*_*522 6

的函数参数a存储在 中rdi。无需从内存中加载任何内容。

lea eax, [rdi+rdi*4]不计算要从中检索数据的任何内存位置的地址。相反,编译器只是重新利用指令来进行乘法。它存储a + a*4eax. 我们称之为 value t

lea eax, [rdi+rax*2]然后有效地存储a + t*2eax.

rax也是返回函数返回值的寄存器。

所以返回值将是a + t*2which a + (a + a*4)*2iswhich a + a*5*2iswhichis a*11

  • @KaKkoi它计算(加载)地址操作数指定的有效地址。它不会从计算出的有效地址加载任何内容,例如具有相同地址操作数的“mov”。 (2认同)