assembly - la 和 addi 在 MIPS asm 中复制寄存器的区别
问题描述
我是 MIPS 的新手,对一个概念感到困惑。
我有一个5
存储在 中的值$s5
,我想将它复制到$a0
以便我可以使用li $v0, 1
它来打印它。我有两种复制方式。
addi $a0, $s5, 0
la $a0, 0($s5)
1. 或 2. 可以打印值5
,如果我这样做li $v0, 1
/syscall
之后(MARS 的 print-integer 系统调用)。
但为什么它适用于 2.?2. 存储$s5
at的地址$a0
,但我们需要一个值,而不是地址。
这会由 print_integer 自动处理吗?
解决方案
首先,la
不是 MIPS 硬件指令,只是汇编器实现的伪指令,如li
. (通常用lui
/addiu
在寄存器中构造一个 32 位的符号地址,如果你按正常方式使用它的话la $reg, symbol
)。查看反汇编/机器代码输出,例如 MARS 在您组装时向您显示。
您可以通过使用寄存器寻址模式而不是符号名称la
来滥用。move
(move
是另一个伪指令;MIPS 没有硬件移动,您只需添加 with$zero
或立即数0
。)
如果汇编器选择了那个,那la
它就可以准确地addi $a0, $s5, 0
组装起来。(虽然它更有可能选择 addiu;立即数不是 0 必须不捕获有符号溢出。一般来说,你永远不需要 add/addi,只需要 addu/addiu。)
2 将 $s5 的地址存储在 $a0 中,但我们需要一个值,而不是地址。这会由 print_integer 自动处理吗?
不,无论哪种方式,值$a0
都是相同的,就像您确实move $a0, $s5
喜欢正常人一样。所以 print_integer 整理出来的最终结果没有区别。
您不能获取寄存器的地址。寄存器可以保存内存地址,但您不能获取寄存器的地址。
是la
的“获取其源操作数的地址”,但请注意,这0($s5)
不是寄存器,它是内存寻址模式的语法,它引用 in 地址处的内存$s5
,就像您可以使用 with 一样lw
。该内存的地址只是$s5
.
C 等效项是int *a0 = &*s5;
& 取消一元*
解引用的地方。