当我使用它们获取地址时,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
之类的内容无效,但我没有看到它。有人能帮助我理解这个吗?提前谢谢!
答案 0 :(得分:8)
当绝对地址是链接时间常量时,mov r32, imm32
和lea 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)
另请注意,您可以使用符号常量作为大小。您还可以更好地格式化和评论您的代码。 (在具有较长助记符的一些指令的代码中,缩进操作数看起来不那么混乱)。
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