ar db "Defference $"
有什么区别
mov dx,offset ar
和
lea dx,ar
我认为两者都在做同样的工作,但这两者之间有什么区别
在这个用例中,LEA 和 MOV 做同样的事情。如果您想以更复杂的方式计算地址,LEA 比 MOV 更强大。
例如,假设您想获取数组中第 n 个字符的地址,并且 n 存储在 bx 中。使用 MOV,您必须编写以下两条指令:
Mov dx, offset ar
add dx, bx
使用 lea 您只需一条指令即可完成:
lea dx, [ar + bx]
这里要考虑的另一件事:该add dx,bx
指令将更改 CPU 的状态标志。lea dx, [ar + bx]
另一方面,在指令内完成的加法不会以任何方式更改标志,因为它不被视为算术指令。
如果您想在进行一些简单计算(地址计算非常常见)时保留标志,这有时会很有帮助。存储和恢复标志寄存器是可行的,但操作缓慢。
引用自 X86 处理器的汇编语言,7e,KIP R. IRVINE
无法使用 OFFSET 来获取堆栈参数的地址,因为 OFFSET 仅适用于编译时已知的地址。以下语句将无法组合:
mov esi,OFFSET [ebp-30] ; error
您可以使用它们来做同样的事情,但LEA
如果地址有点复杂,总是会更好。
考虑到您有以下字符数组:
ASC_TBL DB '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
如果您想获得第 6 个元素“5”,您可以使用以下方法执行以下操作offset
:
mov ax, offset ASC_TBL
add ax, 5h; flags [PF] will be affected
另一方面,如果您使用的是指令LEA
,您可以简单地使用如下指令:
LEA ax, [ASC_TBL + 5h]; no flags are affected
请注意:
虽然 usingLEA
证明它比 using 有优势,但如果地址写起来不是很复杂,或者它们都用相同数量的指令做同样的事情,那么使用offset
它会更有效。offset
原因是它offset ASC_TBL
是在翻译过程中计算的——就像被预处理一样——但是,LEA
它是一条实际的处理器指令。
您不能使用该offset
指令来获取编译时间之前不知道的地址。