从未真正使用过lea (%rax), %rdx
. Use mov %rax, %rdx
相反,因为 CPU 运行效率更高,并且两种方式都会复制寄存器value(无论该值是否是有效的指针)。
LEA 只能工作在内存寻址模式下,不能工作在裸寄存器上。 LEA 有点“撤销”括号,获取地址计算的结果而不是该地址处内存中的值。如果一开始就没有内存操作数,这种情况就不会发生。
这使您可以使用它对任意值执行移位/添加操作,无论它们是否是有效的指针:对不是地址/指针的值使用 LEA? https://stackoverflow.com/questions/46597055/using-lea-on-values-that-arent-addresses-pointers LEA uses内存操作数语法和机器代码将移位/加法操作编码为单个指令,使用 CPU 硬件已经知道如何解码的 x86 正常寻址模式编码。
相比mov
,就像一个C&
地址运算符。而且你不能获取寄存器的地址。 (或者在 C 语言中,aregister
多变的。)您只能使用它来撤消取消引用。
register char *rax = ...;
register char dl = *rax; // mov (%rax), %dl
register char *rcx = rax; // mov %rax, %rcx
register char *rdi = &rax[0]; // lea (%rax), %rdi // never do this, mov is more efficient
register char *rbx = &rax[rdx*4 + 1234]; // lea 1234(%rax, %rdx, 4), %rbx // a real use-case
register char **rsi = &rax; // lea %rax, %rsi // ERROR: can't take the address of a register
当然,如果你要求一个实际的 C 编译器来编译它,你会得到mov %rax, %rdi
, not lea (%rax), %rdi
,即使它没有优化代码。这是概念上的等价物,使用 C 语法和运算符来解释汇编,而不是展示任何内容将如何或应该如何实际编译。