MIPS中括号的作用是什么?

What is the function of parentheses in MIPS?

我一直在研究一本介绍 MIPS 的项目书,但遇到了一个问题。书中有一行代码是lb $t3, ($t2)。我不知道括号是做什么用的,因为在此之前,我还没有看到它们被使用过,而且这本书一开始也没有提到它们。为什么代码不只是 lb $t3, $t2?

这种情况下的括号没有任何区别。

lw这样的一些指令可以使用寄存器值的立即偏移量,例如lw $t3, 16($t2)。这意味着加载 $t3 内存中的内容 $t2 + 16.

MIPS 寻址模式语法是 constant($reg).

($t2) 允许作为 0($t2) 的特例简写。同样的指令可以做
lb $t3, 13($t2) 从地址 13 + $t2 的内存加载(并符号扩展)一个字节到寄存器 $t3

MIPS 唯一的寻址方式是reg + sign_extended_imm16;加载/存储指令(包括lblbu)是I型的。在 0($t2) 中省略 0 只是源代码级别的语法细节;机器代码仍然有 16 个零位来编码常量零。

顺便说一句,我忽略了 MIPS 的索引 FP load/store 指令的存在,例如使用 2 个整数寄存器的 lwxc1。它们仅适用于 FP 整数存储版本需要 3 个 GP 寄存器作为输入,但该寄存器文件仅需要 2 个读取端口(用于标量管道)。 (并且架构师显然认为加载和存储之间的对称性比仅为加载提供 2 寄存器寻址模式更重要;这对于大量代码来说是很好且有用的)。
在一些较新的 MIPS 修订版中,还有 lwpc 用于 PC 相对寻址。但是 lw / lb / lbu 等没有位来编码什么类型的寻址模式;它总是 reg + imm16。其他任何东西都需要不同的指令,经典 MIPS 没有任何其他东西。


语义(对于 asm 文本语法的人类读者)是一个取消引用操作,就像在 C int t3 = *t2;t2[0] 中加载指向-值 (lb) 而不是 int tmp = (int)p 将指针复制为整数 (move)。

() 始终是内存操作数,只能与加载或存储指令一起使用。裸寄存器不是内存寻址模式,不能用作加载或存储指令的第二个操作数。

加载/存储指令在寻址模式上需要括号是一件好事,这样您就不会混淆哪个操作数是地址,哪个是值 .例如sw $t3, 12($t2)$t3 中的字存储到地址12+$t2 的内存中的一个字中。如果 sw $t3, $t2 是有效的语法,您可能会忘记 MIPS 上的内存指令地址总是正确的(就像大多数 RISC),即使所有其他指令都将目标作为第一个操作数。

这使得它在视觉上与 move $t3, $t2 截然不同。能够在代码块中发现加载和存储非常好。

如果您正在设计自己的 MIPS 汇编语言语法或编写汇编程序,则可以合法地将 lb $t3, $t2 写成 lb $t3, 0($t2) 的简写形式。但是 asm 语法是由汇编程序(的作者)定义的,而 MIPS 语法的设计者决定不这样做。


prior to this, I haven't seen them used, and the book just doesn't mention them to begin with.

继续阅读;希望这本书在首次介绍新语法后的某个时间继续解释它。教程或书籍向您展示一些代码作为示例而不停下来解释所有内容是完全正常的,尤其是当解释基于尚未达到的概念时。