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

时间:2016-02-18 07:32:30

标签: assembly x86 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'

然后,如果我为lea ecx, [msg + 4]交换mov ecx, msg + 4,它会以不同的方式运行吗?

我试过两个,输出看起来是一样的。但是,我从这个链接What's the purpose of the LEA instruction?中读到,在第一个答案的评论部分,似乎有人声称mov ecx, msg + 4之类的内容无效,但我没有看到它。有人能帮助我理解这个吗?提前谢谢!

1 个答案:

答案 0 :(得分:8)

当绝对地址是链接时间常量时,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,除非您可以利用lea同时对寄存器进行一些有用的数学运算。 (例如:lea ecx, [msg + 4 + eax*4 + edx]

在64位模式下,可以进行RIP相对寻址,使用LEA可以制作有效的位置无关代码(如果映射到不同的虚拟地址,则不需要修改)。使用mov无法实现此功能。见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