【问题标题】:What is the difference between MOV and LEA in terms of retrieving an addressMOV和LEA在检索地址方面有什么区别
【发布时间】:2016-05-30 06:15:27
【问题描述】:

当我使用 mov 和 lea 获取地址时,它们到底有什么区别?

假设我有一个程序打印出从第 5 个字符开始的字符串,其代码如下所示:

section .text
    global _start
_start:
    mov edx, 0x06  ;the length of msg from its 5th char to the last is 6.
    lea ecx, [msg + 4]
    mov ebx, 1
    mov eax, 4
    int 0x80

section .data
msg db '1234567890'

那么,如果我将lea ecx, [msg + 4] 换成mov ecx, msg + 4,它的运行方式会有所不同吗?

我都试过了,结果似乎是一样的。但是,我在第一个答案的评论部分从这个链接What's the purpose of the LEA instruction? 读到,似乎有人声称mov ecx, msg + 4 之类的东西无效,但我没看到。有人可以帮助我理解这一点吗?提前致谢!

【问题讨论】:

  • @Mysticial:这当然是有效的 NASM 语法。
  • @glenjoker:mov 的编码更短,但lea 更灵活,因为它允许您执行lea ecx, [msg + eax*4] 之类的操作。
  • @Mysticial:不,您正在考虑 MASM 语法,它 无效。在 NASM 语法中,它是一个直接常量。 (MASM:mov ecx, OFFSET msg + 4 什么的)。链接器重定位允许符号+位移,因此symbol + 4 仍然是链接时间常数。完全相同的事情发生在为LEA 的有效地址生成 4B 位移。
  • @PeterCordes: 嗯,MASM 语法中的mov ecx, msg+4mov ecx, [msg+4] 的含义不一样吗?我有一段时间没有使用 MASM/TASM,但我记得是这样的。
  • mov reg, label+imm 无论如何都用 MASM 6.14 为我组装。我没有费心去看它组装成什么

标签: assembly x86 nasm


【解决方案1】:

当绝对地址是链接时间常数时,mov r32, imm32lea r32, [addr] 都可以完成工作。 imm32 可以是任何有效的 NASM 表达式。在这种情况下,msg + 4 是链接时间常数。链接器将找到msg 的最终地址,将其加4(因为.o 中的占位符有+4 作为位移)。将字节从 .o 复制到链接器输出时,该最终值将替换 4B 占位符。

lea的有效地址中的4B位移也发生了完全相同的事情。


mov 的编码略短,can run on more execution ports使用mov reg, imm,除非您可以利用lea 同时对寄存器进行一些有用的数学运算。 (例如:lea ecx, [msg + 4 + eax*4 + edx]

在 64 位模式下,RIP 相对寻址是可能的,使用 LEA 可以让您制作高效的位置无关代码(如果映射到不同的虚拟地址,则不需要修改)。 mov 无法实现此功能。见How to load address of function or label into register in GNU Assembler(也包括NASM)和Referencing the contents of a memory location. (x86 addressing modes)

另请参阅 tag wiki 以获得许多好的链接。


另外请注意,您可以使用符号常量来表示大小。您还可以更好地格式化和注释您的代码。 (在一些指令较长的助记符的代码中,缩进操作数看起来不那么混乱)。

section .text
    global _start
_start:
    mov    edx, msgsize - 4
    mov    ecx, msg + 4     ; In MASM syntax, this would be mov ecx, OFFSET msg + 4
    mov    ebx, 1       ; stdout
    mov    eax, 4       ; NR_write
    int    0x80         ; write(1, msg+4, msgsize-4)

    mov    eax, 1       ; NR_exit
    xor    ecx, ecx
    int    0x80         ; exit(0)
    ;; otherwise execution falls through into non-code and segfaults

section .rodata
msg db '1234567890'     ; note, not null-terminated, and no newline
msgsize equ $-msg       ; current position - start of message

【讨论】:

  • 非常详细的解释,它完美地回答了我的问题。感谢您的帮助。
  • 真的很棒的答案。
猜你喜欢
  • 2010-12-14
  • 1970-01-01
  • 2017-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多