MIPS 数组索引使用 lw 中的位移作为已知常量索引?

MIPS array indexing using a displacement in lw for a known constant index?

我正在尝试从 C 语言翻译嵌套数组 p=A[B[6]] 的这行代码,这是我在学习 MIPS 的书中找到的。 因为我很确定书中的解决方案是错误的,或者至少比它需要的要复杂得多。

数组A[]的基地址存放在寄存器$s1中,B[]的基地址存放在$s2中,g的值存放在$s0中。

我对p=A[B[6]]的翻译是(请告诉我是否正确):

lw $t0, 24($s2) #load from memory B[6] in the register $t0
sll $t0, $t0, 2 #$t0=$t0*4
add $t0, $t0, $s1 #add to $t0 the address of A[B[6]]
lw $t0, 0($t0) #$t0=A[B[6]]

而这本书(充满其他错误)提供了这个解决方案:

addi $t0, [=11=], 6
sll sll $t0, $t0 2 
add $t1, $s2, $t0 
lw $t2, 0 ($t1)
sll $t2, $t2 2 
add $t3, $s1, $t2
lw $s0, 0 ($t3)

我的代码正确还是书上的正确?

两个版本在逻辑上都是正确的;书版唯一的问题就是效率很低

基于6是一个assemble时间常数的事实,它无法优化,所以6*4可以是lw中的一个直接位移,而不是在运行时在寄存器中计算并单独添加到基数中。

lw 有 16 位立即数偏移量的空间;不利用并限制自己只使用 0 是愚蠢的。出于某种原因,它是 I 型指令,专门编写大量代码 space 以允许较大的偏移量。

除此之外,您的版本是等效的。书籍版本在寄存器中计算 6<<2 并将其添加到 B ($s2) 的基数。它通过添加到零寄存器来将初始 6 放入寄存器中。

你的和书中的都使用 add 而不是 addu。不确定为什么要捕获有符号溢出,尤其是在进行地址数学运算时。 C 编译器通常总是使用 addu。 (有符号溢出在 C 语言中是未定义的行为,但编译器开发人员知道通常更有用/期望它静默包装比引发异常。)