la 和 addi 在 MIPS asm 中复制寄存器的区别

Difference in la and addi to copy a register in MIPS asm

我是 MIPS 的新手,对一个概念感到困惑。

我有一个值 5 存储在 $s5 中,我想将它复制到 $a0 以便我可以使用 li $v0, 1 打印它。我有两种复制方式。

  1. addi $a0, $s5, 0
  2. la $a0, 0($s5)

如果我在其后执行 li $v0, 1 / syscall (MARS's print-integer syscall).

,则 1. 或 2. 可以打印值 5

但为什么它适用于 2.? 2. 将 $s5 的地址存储在 $a0,但我们需要一个值,而不是地址。

这会由 print_integer 自动处理吗?

首先,la不是MIPS硬件指令,只是assembler实现的伪指令,如li。 (通常用 lui / addiu 在寄存器中构造一个 32 位符号地址,如果你像 la $reg, symbol 一样正常使用它)。查看反汇编/机器代码输出,例如就像 MARS 在您 assemble.

时显示的那样

您可以将 la 滥用为 move,方法是使用寄存器寻址模式而不是符号名称。 (move 是另一个伪指令;MIPS 没有硬件移动,您只需添加 $zero 或立即数 0。)

如果 assembler 选择 la 可以 assemble 准确地达到 addi $a0, $s5, 0。 (尽管它更有可能选择 addiu;除 0 以外的立即数必须不陷入有符号溢出。一般来说,你永远不需要 add/addi,只需要 addu/addiu。)

2 is storing the address of $s5 at $a0, but we need a value, not an address. Will this be automatically handled by print_integer?

不,$a0 中的值无论哪种方式都是相同的,就像您像普通人一样 move $a0, $s5 一样。所以print_integer整理的最终结果没有区别。

你不能获取寄存器的地址。一个寄存器可以保存一个内存地址,但是你不能取寄存器的地址。

是其源操作数的la "takes the address",但请注意0($s5)不是寄存器,它是内存寻址模式的语法,它指的是内存$s5 中的地址,就像您可以使用 lw 一样。 内存的地址就是$s5.

C 等价物是 int *a0 = &*s5;,其中 & 取消了一元 * 取消引用。