【问题标题】:Difference between lea and offsetlea 和 offset 的区别
【发布时间】:2011-02-17 08:28:31
【问题描述】:
ar db "Defference $"

有什么区别

mov dx,offset ar

lea dx,ar

我认为两者都在做同样的工作,但这两者之间有什么区别

【问题讨论】:

标签: assembly x86 masm tasm


【解决方案1】:

在这个用例中,LEA 和 MOV 做同样的事情。如果您想以更复杂的方式计算地址,LEA 比 MOV 更强大。

例如,假设您想获取数组中第 n 个字符的地址,并且 n 存储在 bx 中。使用 MOV 你必须编写以下两条指令:

Mov dx, offset ar
add dx, bx

使用 lea,您只需一条指令即可完成:

lea dx, [ar + bx]

这里要考虑的另一件事:add dx,bx 指令将更改 CPU 的状态标志。另一方面,在 lea dx, [ar + bx] 指令中完成的加法不会以任何方式更改标志,因为它不被视为算术指令。

如果您想在进行一些简单计算(地址计算非常常见)时保留标志,这有时会很有帮助。存储和恢复标志寄存器是可行的,但操作缓慢。

【讨论】:

  • 还有offset ar - 是在翻译过程中计算的即时值。而lea - 是实际的处理器指令“加载有效地址”,第二个操作数引用内存。
  • @ony: lea 只是一个移位加指令。它实际上从未从内存中加载,它只是使用寻址模式语法和二进制编码。在 OP 的情况下,lea 在绝对地址上,disp16movimm16 相同,两者在汇编时以相同的方式计算(实际上是在链接时最终地址为已知)。
  • @PeterCordes,我没有说lea 加载任何东西(参考只是参考)。我说它是真正的 x86 指令。如果您在翻译过程中进行计算,您可以使用mov
  • lea 最让我困惑的是编译器和调试器使用的语法。 lea ax, [addr] 对我来说就像“用addr内容 做一些事情,然后将结果放入ax,事实并非如此。
  • 另外,这在早期的 16 位实模式编程中也是一个问题。当链接到所有内容都在同一段中的小型二进制 .com 文件时,您可以在大多数情况下交替使用 offsetlea,但使用 tiny 以外的内存模型会导致很多问题,因为offset 相对于定义数据的段基地址。
【解决方案2】:

引自 Assembly Language for x86 Processors, 7e, KIP R. IRVINE

无法使用 OFFSET 来获取堆栈参数的地址,因为 OF​​FSET 仅适用于编译时已知的地址。以下语句将无法组合:

mov esi,OFFSET [ebp-30]        ; error

【讨论】:

    【解决方案3】:

    您可以使用它们来做同样的事情,但如果地址有点复杂,LEA 总是会更好。

    假设您有以下字符数组:

    ASC_TBL DB '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'

    如果您想获得第 6 个元素“5”,您可以使用 offset 执行类似的操作:

    mov ax, offset ASC_TBL
    
    add ax, 5h; flags [PF] will be affected 
    

    另一方面,如果您使用LEA 指令,您可以像这样简单地使用一个 指令:

    LEA ax, [ASC_TBL + 5h]; no flags are affected

    注意:

    • 虽然使用LEA 证明它比使用offset 有优势,但如果地址写起来不是很复杂,或者两者都会用相同的方式做同样的事情,使用offset 会更有效指令数。 原因是offset ASC_TBL 是在翻译过程中计算出来的——就像被预处理一样——但是,LEA 是一个实际的处理器指令。

    • 您不能使用offset 指令来获取编译时间之前不知道的地址。

    【讨论】:

    • mov ax, offset ASC_TBL + 5 是合法的,并且更短(mov ax, imm16 为 3 个字节,LEA 为 4 个字节:操作码 + modrm + disp16)。无论哪种方式,绝对地址都由汇编器(或链接器)计算并嵌入到机器代码中。 ASC_TBL+5 是链接时间常数,就像 ASC_TBL 一样;没有+5 在运行时完成。符号在运行时并不真正存在,除了作为可执行文件中的调试元数据。运行引用它们的指令时,CPU 不会搜索它们。
    • 我不是说+5是在运行时完成的,我说完整的LEA指令是一个实际的处理器指令
    • 好的,所以你只是不知道你可以mov ax, offset ASC_TBL + 5。嗯,你可以。 :P 汇编器(如果您不制作平面二进制文件,则为链接器)使用与填充 lea 操作数中的 [disp16] 字段相同的机制来处理它。 mov reg, imm16 编码也只需要机器代码中的绝对地址。 LEA 对代码大小的影响更差,不应该用于此,除非在 64 位代码中使用 RIP 相对寻址来获得位置无关性或代替 64 位绝对地址。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    • 2016-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多