assembly MOV和莱亚在检索地址方面有何区别

jbose2ul  于 2023-03-08  发布在  其他
关注(0)|答案(1)|浏览(140)

当我用mov和莱亚来获取地址时,它们到底有什么区别?
假设我有一个程序从第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之类的东西是无效的,但我没有看到。有人能帮我理解一下吗?提前感谢!

sh7euo9m

sh7euo9m1#

当绝对地址是一个链接时间常量时,mov r32, imm32lea r32, [addr]都可以完成任务。imm32可以是任何有效的NASM表达式。在这种情况下,msg + 4是一个链接时间常量。链接器将找到msg的最终地址。加上4(因为.o中的占位符的位移为+4)。当从.o复制字节到链接器输出时,最终值将替换4B占位符。
lea的有效地址中的4B位移也会发生完全相同的情况。
mov的编码略短(无ModRM字节),而can run on more execution ports也可参见https://uops.info/(汇编+链接,然后分解为GAS英特尔语法,而非NASM)。

08049000 <foo>:
 8049000:       b8 00 90 04 08          mov    eax,0x8049000
 8049005:       8d 05 00 90 04 08       lea    eax,ds:0x8049000

使用mov reg, imm,除非您可以利用lea同时对寄存器进行一些有用的运算。(例如:(一个月一个月一个月)

在64位模式下,RIP相对寻址是可能的,使用莱亚可以让您生成有效的位置无关代码(如果Map到不同的虚拟地址,则不需要修改)。使用mov无法实现该功能。请参阅How to load address of function or label into register和引用内存位置的内容。(x86寻址模式)
还可以查看x86tag 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

相关问题