【发布时间】:2012-05-24 15:08:11
【问题描述】:
有什么区别
LEA $1000,A0
和
MOVE #$1000,A0
将地址放入地址注册表?
【问题讨论】:
有什么区别
LEA $1000,A0
和
MOVE #$1000,A0
将地址放入地址注册表?
【问题讨论】:
在这种情况下,不会有可观察到的差异(与公认的答案声称不同 - MOVE 示例将组装为 MOVEA,它不会改变 CCR,请参阅 M68K 参考手册第 4-116 页到4-120)。
【讨论】:
lea 指令不会影响标志,而move 指令会。具体Z和C会在move #$1000,a0之后被清除。
【讨论】:
move 不会影响标志(因为它正在写入地址寄存器)。
Durandal 是正确的,涉及地址寄存器的操作通常对处理器标志没有影响,在这种特殊情况下,两条指令的行为相同并且占用完全相同的 CPU 时间(使用短寻址模式为 8 个周期或使用长寻址模式为 12 个周期)模式)。
MOVE xx,an 不是真正的指令,它是汇编程序允许的,但如果您查看反汇编结果,您会发现实际指令是 MOVEA。
【讨论】:
拥有 LEA 而不仅仅是 MOVE,其动机是 LEA 允许访问基于不同寻址模式的地址计算结果。
MOVE #$1000,A0 指令将立即数 $1000 移动到 A0 寄存器中,因为在助记符中使用了立即数指示“#”。 LEA $1000,A0 指令指向内存地址 $1000,并将此地址加载到 A0 寄存器中。在这个简单的示例中,结果是相同的,看起来只是一些简单的语法问题,缺少立即指示“#”。
查看以下差异时,LEA 的实际作用可能更容易理解:
LEA (A0),A1
和:
MOVE (A0),A1
使用LEA (A0),A1,A1 寄存器加载A0 值,如A1 := A0,其中MOVE (A0),A1 从A0 寄存器中的内存位置加载字(默认大小)值, 符号将值扩展为 long(地址寄存器总是整个寄存器)并将值保存在 A1 寄存器中。
所以LEA 提供了在地址实际进行内存访问之前地址计算的地址结果。这也是为什么没有任何LEA #<data> 格式(寻址模式)的原因,因为#<data> 的地址将在程序空间(PC 相对)中,因为立即数数据是指令的一部分。
当使用更复杂的寻址模式时,LEA 的真正优势显而易见,否则需要大量代码来计算地址。
因此,原始问题中LEA 和MOVE 的实际区别可以用地址寄存器目标(可能用于数据寄存器目标)的非法代码更好地说明:
LEA ($1000),A0
和:
MOVE #$1000,A0
这更清楚地表明LEA 提供了间接地址,而不实际进行内存访问。
【讨论】:
LEA (A0),A1 相当于一个简单的A1 := A0 赋值吗?我觉得这很令人惊讶,因为(A0) 是间接寻址模式,人们期望它的意思是:将A0 指向的数据加载到A1。
(A0)给出的间接地址是什么?而当LEA给出源参数的地址时,那么LEA (A0), ...中源的值是多少?
A0的值只是被复制到A1中,我在这里无法弄清楚括号符号(A0)的含义,除非@ 987654356@ 行为暗示提取源参数的地址。考虑到这一点,LEA Table,A0(文档中的示例)会做什么? (我猜每种语言都有其不合逻辑/令人困惑的特征)
(A0) 中的括号表示法是间接的,所以在做MOVE 时,会访问A0 给出的地址处的数据。对于LEA Table,A0,则意味着获取Table 的地址,因为table 是地址值,而不是立即数,上面的答案也涵盖了这一点。你可以下载EASy68K模拟器试试这个。
LEA ($1000).w,A0 和 LEA ($1000).l,A0 实际上是 LEA 的有效有效寻址模式。
当我学习如何用汇编语言 (68k) 编程时,在处理地址寄存器时,LEA 和 MOVE.L 的这个例子中指出了不同之处。在使用标签方面,肯定有很大的不同。
假设你有一个标签Foo 代表一些DC.*。
LEA Foo, A0 ;Loads Foo into Address Register A0
MOVE.L #Foo, A0 ;Loads Foo into Address Register A0
教训是,在正常情况下,上述两条指令实际上会完成同样的事情。但是,由于现实系统中的“可重定位性”,底部的可能会导致问题。
只使用LEA 方法是最安全的。使用$1000 时是否会出现问题 - 我不确定。但是,在处理地址寄存器时要谈论这个LEA 和MOVE.L 之间的区别,这绝对是必须考虑的事情。
【讨论】: