在检索地址方面,MOV和LEA之间有什么区别

gle*_*ker 4 x86 assembly nasm

当我使用它们获取地址时,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'
Run Code Online (Sandbox Code Playgroud)

然后,如果我换lea ecx, [msg + 4]mov ecx, msg + 4,将它运行不同?

我试过两个,输出看起来是一样的.但是,我从这个链接中读到,LEA指令的目的是什么?,在第一个答案的评论部分,似乎有人声称有类似mov ecx, msg + 4无效的东西,但我没有看到它.有人能帮助我理解这个吗?提前致谢!

Pet*_*des 8

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

lea有效地址中的4B位移恰好发生了同样的事情.


mov编码略短,可以在更多的执行端口上运行. 除非您可以同时利用寄存器进行有用的数学运算,否则请使用movlea.(例如:lea ecx, [msg + 4 + eax*4 + edx])

在64位模式下,可以进行RIP相对寻址,使用LEA可以创建有效的位置无关代码(如果映射到不同的虚拟地址则不需要修改).没有办法实现这个功能mov.请参阅引用内存位置的内容.(x86寻址模式)

另请参阅 标记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
Run Code Online (Sandbox Code Playgroud)