Assembly lea和offset之间的差异

Assembly lea和offset之间的差异,assembly,x86,masm,tasm,Assembly,X86,Masm,Tasm,两者之间有什么区别 ar db "Defference $" 及 我认为两者都在做相同的工作,但是在这个用例中,这两个之间的区别是什么。如果您想以更复杂的方式计算地址,LEA比MOV更强大 例如,假设您想要获取数组中第n个字符的地址,并且n存储在bx中。使用MOV,您必须编写以下两个说明: lea dx,ar 使用lea,您只需一个指令即可完成: Mov dx, offset ar add dx, bx 这里要考虑的另一件事: AddixDX,BX指令将改变CPU的状态标志。另一方面,在l

两者之间有什么区别

ar db "Defference $"


我认为两者都在做相同的工作,但是在这个用例中,这两个之间的区别是什么。如果您想以更复杂的方式计算地址,LEA比MOV更强大

例如,假设您想要获取数组中第n个字符的地址,并且n存储在bx中。使用MOV,您必须编写以下两个说明:

lea dx,ar
使用lea,您只需一个指令即可完成:

Mov dx, offset ar
add dx, bx

这里要考虑的另一件事:<代码> AddixDX,BX指令将改变CPU的状态标志。另一方面,在

lea dx[ar+bx]
指令内进行的加法不会以任何方式更改标志,因为它不被视为算术指令


如果您希望在执行一些简单计算(地址计算非常常见)时保留标志,这有时会很有用。存储和恢复标志寄存器是可行的,但操作缓慢。

引用x86处理器汇编语言7e,KIP R.IRVINE

不可能使用偏移量来获取堆栈参数的地址,因为偏移量仅适用于编译时已知的地址。以下语句无法汇编:


你可以用它们做同样的事情,但是如果地址有点复杂,
LEA
总是会更好

假设您有以下字符数组:

ASC_TBL数据库'0'、'1'、'2'、'3'、'4'、'5'、'6'、'7'、'8'、'9'、'A'、'B'、'C'、'D'、'E'、'F'

如果要获取第6个元素“5”,可以使用
偏移量执行类似操作:

mov esi,OFFSET [ebp-30]        ; error
另一方面,如果您正在使用
LEA
指令,您可以简单地使用one指令,如下所示:

leaax[ASC_TBL+5h];没有任何标志受影响

请注意:

  • 虽然使用
    LEA
    证明了它比使用
    offset
    有优势,但是如果地址写起来不是很复杂,或者两者都使用相同数量的指令做相同的事情,那么使用
    offset
    会更有效。 原因是
    offset ASC\u TBL
    是在翻译过程中计算的,就像被预处理一样,但是
    LEA
    是实际的处理器指令

  • 不能使用
    offset
    指令获取编译时间之前未知的地址


还有
偏移量ar
-是在转换过程中计算的即时值。和
lea
-是实际的处理器指令“加载有效地址”,第二个操作数引用memmory。@ony:
lea
只是一个移位和加法指令。它从不实际从内存加载,它只使用寻址模式语法和二进制编码。在OP的例子中,当绝对地址上有
lea
时,
disp16
mov
imm16
相同,两者在组装时(实际上是在最终地址已知的链接时)以相同的方式计算。@PeterCordes,我没有说
lea
加载任何内容(引用只是一个引用). 我说过这是一条真正的x86指令。如果你在翻译过程中进行计算,你可以使用
mov
lea
最让我困惑的是编译器和调试器使用的语法
leaax,[addr]
对我来说“对
addr
的内容执行一些操作,并将结果放入
ax
,但事实并非如此。此外,这在以前的16位实模式编程中也是一个问题。当链接到一个所有内容都在同一段中的小binary.com文件时,您可以在大多数情况下互换使用
offset
lea
,但是使用非
tiny
的内存模型会导致很多问题,因为
偏移量
与定义数据的段基址有关。它们之间的唯一区别是
lea
是一条指令,
偏移量
不可能与
mov ax重复,偏移量ASC_TBL+5
合法且较短(mov ax为3字节,imm16为4字节,LEA为4字节:操作码+modrm+disp16)。无论哪种方式,绝对地址都由汇编程序(或链接器)计算并嵌入到机器代码中
ASC_TBL+5
是一个链路时间常数,就像
ASC_TBL
一样;运行时没有执行
+5
。符号在运行时并不真正存在,除非作为调试元数据存在于可执行文件中。CPU在运行引用它们的指令时没有搜索它们。我没有说
+5
是在运行时完成的,我说完整的
LEA
指令是一条实际的处理器指令ok,所以你只是不知道你可以
mov ax,offset ASC\u TBL+5
。嗯,你可以P汇编器(如果您没有生成平面二进制文件,则为链接器)使用与它们在
lea
操作数中填充
[disp16]
字段相同的机制来处理它。
mov reg,imm16
编码也只需要机器代码中的绝对地址。LEA在代码大小方面更差,因此永远不应用于此目的,除非在64位代码中使用RIP相对寻址以获得位置独立性,或代替64位绝对地址。
lea dx, [ar + bx]
mov esi,OFFSET [ebp-30]        ; error
mov ax, offset ASC_TBL

add ax, 5h; flags [PF] will be affected