我是汇编语言的新手。我目前正在阅读本组装指南。我对 LEA 指令有疑问。我对LEA指令的理解是用源操作数的有效地址LEA加载目标操作数
下面的例子来自同一个链接。
lea edi, [ebx+4*esi] — the quantity EBX+4*ESI is placed in EDI.
lea eax, [var] — the value in var is placed in EAX.
lea eax, [val] — the value val is placed in EAX.
Run Code Online (Sandbox Code Playgroud)
在上面的第二个和第三个示例注释中,该值已加载到 EAX 中。这是我的困惑。请让我知道是否可以使用 LEA 指令加载目标操作数中的有效地址和值。
上图来自 youtube 的 Open SecurityTraining 频道的汇编语言简介。
谢谢你。
LEA 是 ALU shift+add 指令,它使用寻址模式语法和机器代码编码来利用硬件支持对此类操作进行解码。(它不关心输入是否是地址,所以你的问题的第二部分在那里得到了回答:有效地lea eax, [ecx + eax*2]实施x*2 + y。)
在任何情况下都lea不会从内存中加载或存储。请参阅英特尔的说明手册条目。
有趣的事实:唯一的例外是 ModR/M 字节编码的是寄存器源而不是内存。例如lea eax, eax,如果你的汇编器没有拒绝汇编它,或者你用db伪指令手动编码它,就会出现#UD(未定义指令)的错误。如果您使用 asm 而不是十六进制机器代码编写,这在实践中不需要担心。但是它不能采取任何依赖于数据的例外;它根本不在乎它在运行什么值。
在第三个中,我认为他们在谈论诸如val equ 4or 之类的东西val = 4,所以“”的值val是一个汇编时间常数,而不是存储在内存中。
是的,您可以为此使用 LEA(或任何 32 位常量),但mov eax, val更短且更高效。使用具有绝对disp32寻址模式的 LEA毫无意义。
有趣的事实:MASM 忽略[]了汇编时常量: mov eax, [val]is a mov eax, imm32,与mov eax, val. Ross Ridge在 MASM32 中的混淆括号上写了一个很好的答案。
lea eax, [var] — the value in var is placed in EAX.
Run Code Online (Sandbox Code Playgroud)
评论是错误的。的地址的var被放置在EAX。在正常的ASM术语,该值在一个符号名字的意思是在该地址存储在存储器中的值。
mov eax, OFFSET var比 更高效、更短lea eax, [var]。有些人喜欢写作lea是因为对人类读者来说是“语义”的意思:取地址。但是,如果您在装配中写作,人类可读性应该在效率之后出现,并且只赢为延续断路器,例如选择esi选择没有其他差异时选择源指针。(很好地格式化/缩进您的代码,并对其进行很好的注释。)
lea eax, [var + edi]是有道理的,你不能用mov. 但是您可以这样做mov eax, OFFSET var + 1234,因为汇编器 + 链接器必须能够支持填充 32 位符号 + 偏移值以用于诸如[var + 1234].
在 64 位模式下,lea rax, [rel var]在与位置无关的代码中是有意义的:您无法使用mov.