LEA和MOVE.L之间的区别是什么?

9

这两者之间有什么区别吗?

LEA $1000,A0

并且

MOVE #$1000,A0

将地址放入地址注册表中?
5个回答

10
在这种情况下,不会有任何可观察到的差异(与被接受的答案声称的不同 - MOVE示例将组装为MOVEA,它不会改变CCR,请参见M68K参考手册第4-116至4-120页)。

6
lea指令不影响标志位,而move指令会有影响。具体来说,在执行move #$1000,a0后,ZC会被清除。

现在我很少写汇编语言了,但我经常查看由gcc生成的汇编代码,以检查它是否再次出错。但是当我拥有基于68k的计算机(Atari ST :-)时,编写汇编语言是加速关键例程的常见任务。 - Gunther Piez
如果您感兴趣的话,还有一个小差别 :) http://stackoverflow.com/questions/10766855/why-address-register-postincrement-is-a0 - dynamic
另一个答案说,这个特定的“move”不会影响标志位(因为它正在写入地址寄存器)。 - Peter Cordes

5
Durandal是正确的,在涉及地址寄存器的操作通常不会影响处理器标志,特别是在这种情况下,这两个指令将表现相同并且需要相同的CPU时间(使用短地址模式需要8个周期或长模式需要12个周期)。
MOVE xx, an不是真正的指令,它是汇编器允许的一种方式,但如果您查看反汇编结果,您会发现实际指令是MOVEA。

1
拥有LEA而不仅是MOVE的动机在于,LEA基于不同的寻址模式提供了访问地址计算结果的方式。
指令MOVE #$1000,A0将立即数$1000移入寄存器A0,因为助记符中使用了立即数标识"#"。指令LEA $1000,A0将指向内存地址$1000,并将该地址加载到寄存器A0中。在这个简单的例子中,结果相同,看起来只是一些简单的语法问题,缺少了立即数标识"#"。
当看到以下区别时,可能更容易理解LEA的实际作用:
LEA (A0),A1

并且:

MOVE (A0),A1

使用LEA (A0),A1指令,将A0的值加载到A1寄存器中,类似于A1 := A0。而MOVE (A0),A1指令则从A0寄存器中加载字(默认大小)的值,对值进行符号扩展至长整型(地址寄存器始终为整个寄存器),并将该值保存在A1寄存器中。

因此,LEA提供了地址计算结果,然后再用该地址实际访问内存。这也是为什么没有LEA #<data>格式(寻址模式),因为#<data>的地址在程序空间中(PC相对),因为立即数据是指令的一部分。

当使用更复杂的寻址模式时,LEA的真正优势就显现出来了,否则需要编写大量代码来计算地址。

因此,在原问题中,LEAMOVE的实际区别可以更好地用以下非法代码来说明地址寄存器目的地(可能适用于数据寄存器目的地):

LEA ($1000),A0

并且:

MOVE #$1000,A0

这更清晰地显示了LEA提供间接寻址的地址,而实际上并没有进行内存访问。

你确定 LEA (A0), A1 相当于简单的 A1 := A0 赋值吗?我觉得有点奇怪,因为 (A0) 是间接寻址模式,人们会期望它的意思是:A0 指向的数据加载到 A1 - XouDo
问问自己,(A0) 所代表的间接寻址的地址是什么?当 LEA 提供源参数的地址时,LEA (A0), ... 中的源参数的值是什么? - Morten Zilmer
我理解你的意思,但是如果A0的值只是被复制到A1中,我无法理解括号符号(A0)在这里的含义,除非LEA操作暗示提取源参数的地址。考虑到这一点,文档中的例子LEA Table,A0会做什么呢?(我猜每种语言都有其不合逻辑/令人困惑的特点) - XouDo
1
(A0)中的括号符号是一种间接寻址方式,因此在进行MOVE操作时,将访问由A0给出的地址处的数据。关于LEA Table,A0,它意味着获取Table的地址,因为Table是一个地址值,而不是立即数,这也在上面的答案中有所涉及。您可以通过下载EASy68K模拟器来尝试此操作。 - Morten Zilmer
请注意,LEA($1000)。w,A0LEA($1000)。l,A0实际上是有效的LEA寻址模式。 - flamewing
这是否意味着 lea (A0),A1 等同于 movea.l A0,A1?我想知道是否存在无法通过调整的 movea 表达 lea 的情况。我认为 lea ($1234,A0),A0 可能是其中之一,但你可以使用 adda.l #$1234,A0 - Robert S.

0
当我学习汇编语言(68k)编程时,有人指出了在处理地址寄存器时使用LEAMOVE.L的区别。在使用标签方面,确实存在重大差异。
假设您有一个标签Foo用于某个DC.*
LEA Foo, A0       ;Loads Foo into Address Register A0

MOVE.L #Foo, A0   ;Loads Foo into Address Register A0

这个教训告诉我们,在正常情况下,上述两个指令实际上会完成相同的事情。然而,在现实系统中由于“可重定位性”,下面的指令可能会引起问题。

最安全的方法是只使用LEA方法。关于在使用$1000时是否会出现问题,我不确定。然而,当处理地址寄存器时,谈论这种LEAMOVE.L之间的区别,这绝对是必须考虑的。


1
我认为这个语句并不完全正确。的确存在“可重定位性”的差异,但仅当您使用了lea的pc相对模式时。LEA Foo(pc),A0是确实是位置无关的,但是像move.l #Foo,A0这样的LEA Foo,A0将会由汇编器为标签引用生成一个重定位表。当然,pc相对版本也有一些缺点,所涉及的标签必须在指令的+/-32k字节处。 - Mickaël Pointier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接