当我用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
之类的东西是无效的,但我没有看到。有人能帮我理解一下吗?提前感谢!
1条答案
按热度按时间sh7euo9m1#
当绝对地址是一个链接时间常量时,
mov r32, imm32
和lea 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)。使用
mov reg, imm
,除非您可以利用lea
同时对寄存器进行一些有用的运算。(例如:(一个月一个月一个月)在64位模式下,RIP相对寻址是可能的,使用莱亚可以让您生成有效的位置无关代码(如果Map到不同的虚拟地址,则不需要修改)。使用
mov
无法实现该功能。请参阅How to load address of function or label into register和引用内存位置的内容。(x86寻址模式)还可以查看x86tag wiki以获得许多好的链接。
还需要注意的是,你可以使用一个符号常量来表示大小,也可以更好地格式化和注解代码(缩进操作数在一些指令的助记符较长的代码中看起来不那么混乱)。