汇编语言 - 可以使用LEA指令加载值

时间:2018-02-17 15:22:52

标签: assembly x86 masm

我是汇编语言的新手。我目前正在经历这个Assembly Guide。我对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.

在上面的第2和第3个示例中,注释表示该值已加载到EAX中。这是我的困惑。如果LEA指令可用于加载有效地址以及目标操作数中的值,请告诉我。

Introduction to assembly language

以上图片来自youtube的开放式安全培训渠道Introduction to assembly language

谢谢。

2 个答案:

答案 0 :(得分:4)

LEA是ALU shift + add指令,它使用寻址模式语法和机器代码编码来利用硬件支持来解码这种操作。 (How to protect cells in Excel but allow these to be modified by VBA script,因此问题的第2部分会在那里得到解答:lea eax, [ecx + eax*2]有效地实施x*2 + y。)

lea在任何情况下都不会从内存中加载或存储。请参阅It doesn't care if the inputs are addresses or not

有趣的事实:它可以采取的唯一例外是ModR / M字节是否编码寄存器源而不是内存。例如如果你的汇编程序没有拒绝汇编它,或者你用lea eax, eax伪指令手动编码它,那么db就会出现#UD(UnDefined指令)。如果您在asm中编写,而不是在十六进制机器代码中编写,那么这在实践中并不值得担心。但它没有数据依赖的例外;它完全不关心它正在运行的是什么值。

在第3个中,我认为他们谈论的是val equ 4val = 4之类的东西,所以“val”的值是一个汇编时常数,而不是存储在存储器中。

是的,你可以使用LEA(或任何32位常数),但mov eax, val更短,效率更高。使用具有绝对disp32寻址模式的LEA是没有意义的。

有趣的事实:MASM忽略[]组装时间常数:mov eax, [val]mov eax, imm32,与mov eax, val相同。 Ross Ridge在Intel's instruction-manual entry for it上写了一个很好的答案。

lea eax, [var] — the value in var is placed in EAX.

评论错误。 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的RIP相对地址。

答案 1 :(得分:2)

LEA实际上是#34;加载有效地址。"它首先计算一个地址 - 称为"有效"因为它可能由几个部分组成,结果是有效地在目的地中结束 - 并且加载到某处的地址。
虽然[var]使用寻址模式,{{ 1}}仅仅计算地址并将其存储在目标位置,它不会使用它来从主存储器加载某些东西。 " var"中的值错了,"值var"更重要的是,如果" var"是指标签的地址,而不是存储的值。

由于源明确表示" [...]未加载内存位置的内容,因此只计算有效地址并将其放入寄存器中,"我认为这只是一个误导性的错字,而不是错误的信息。