leaq 的第一个操作数必须是内存地址,第二个操作数必须是寄存器吗?
Must the first operand of leaq be a memory address and the second operand be a register?
在ATT汇编语言中,使用leaq指令时,其第一个操作数是否必须是内存地址而不是寄存器或常量(前缀$
)?它的第二个操作数必须是寄存器吗?我从阅读《计算机系统:程序员的视角》中得到了这种印象,并且从未见过与我的猜测不同的例子。谢谢
是的,没错。虽然技术上可以对具有两个寄存器操作数的 lea
进行编码,但这样的编码是无效的并会导致 #UD
异常。有关详细信息,请参阅 this reference or this one。
即使它是可编码的,您也永远不想使用它。
如果你想把一个常量放在一个寄存器中,你不应该使用lea
。 mov 34, %eax
比 lea 1234, %eax
(disp32 寻址模式中的绝对地址)更短且更高效。
LEA 静态地址的唯一用例是具有 RIP 相对寻址模式的 64 位代码,例如 lea symbol(%rip), %rax
(7 字节),在 mov $symbol, %eax
(5 字节)的情况下不可用,因为您需要与位置无关的代码,and/or 地址不适合 32 位零扩展立即数。
有关 mov $symbol, %rdi
为何不是最佳选择的更多信息,请参阅 。
在 32 位代码中,lea symbol, %edi
是 6 个字节(opcode + modrm + disp32),并且在 Intel Sandybridge 系列 CPU 上只运行一个端口 1 或端口 5。 (https://agner.org/optimize/)
mov $symbol, %edi
是 5 个字节 (opcode + imm32 short form with no ModRM byte),并在任何 ALU 端口上运行。
16 位代码相同:mov $symbol, %di
是 3 个字节,而 lea symbol, %di
是 4 个字节,具有相同的执行端口差异。 (或者在 NASM 语法中,lea di, [symbol]
与 mov di, symbol
,或者 GAS .intel_syntax
或 MASM 中的 mov di, OFFSET symbol
。)
不过,LEA 对于 base=register 寻址模式很有用。如果地址适合 32 位符号扩展 disp32,则像 lea symbol(%rdi), %rax
。
或用于任意移位和添加用法,例如 lea 123(%rdi, %rdi, 2), %eax
执行 eax = 3*edi + 123
。
在ATT汇编语言中,使用leaq指令时,其第一个操作数是否必须是内存地址而不是寄存器或常量(前缀$
)?它的第二个操作数必须是寄存器吗?我从阅读《计算机系统:程序员的视角》中得到了这种印象,并且从未见过与我的猜测不同的例子。谢谢
是的,没错。虽然技术上可以对具有两个寄存器操作数的 lea
进行编码,但这样的编码是无效的并会导致 #UD
异常。有关详细信息,请参阅 this reference or this one。
即使它是可编码的,您也永远不想使用它。
如果你想把一个常量放在一个寄存器中,你不应该使用lea
。 mov 34, %eax
比 lea 1234, %eax
(disp32 寻址模式中的绝对地址)更短且更高效。
LEA 静态地址的唯一用例是具有 RIP 相对寻址模式的 64 位代码,例如 lea symbol(%rip), %rax
(7 字节),在 mov $symbol, %eax
(5 字节)的情况下不可用,因为您需要与位置无关的代码,and/or 地址不适合 32 位零扩展立即数。
有关 mov $symbol, %rdi
为何不是最佳选择的更多信息,请参阅
在 32 位代码中,lea symbol, %edi
是 6 个字节(opcode + modrm + disp32),并且在 Intel Sandybridge 系列 CPU 上只运行一个端口 1 或端口 5。 (https://agner.org/optimize/)
mov $symbol, %edi
是 5 个字节 (opcode + imm32 short form with no ModRM byte),并在任何 ALU 端口上运行。
16 位代码相同:mov $symbol, %di
是 3 个字节,而 lea symbol, %di
是 4 个字节,具有相同的执行端口差异。 (或者在 NASM 语法中,lea di, [symbol]
与 mov di, symbol
,或者 GAS .intel_syntax
或 MASM 中的 mov di, OFFSET symbol
。)
不过,LEA 对于 base=register 寻址模式很有用。如果地址适合 32 位符号扩展 disp32,则像 lea symbol(%rdi), %rax
。
或用于任意移位和添加用法,例如 lea 123(%rdi, %rdi, 2), %eax
执行 eax = 3*edi + 123
。