这是高级功能: J[6] = K[d-e]
d = $t0, e = $t1, J = $s1, K = $s2, 最终结果为 $s4
到目前为止,我有:
lw $t2, 24($s1) #Load J[6] into $t2
sub $t3, $t0, $t1 #Subtract e from d to $t3
我知道我不能做的是,lw $t4, $t3($s2)
但我不确定如何翻译 K[$t0 - $t1]。
开始:将此语句翻译成汇编,
J[6] = K[d-e];
首先我们看一下三地址码,这需要我们梳理出更小的操作的方向和顺序:
x1 = d-e # store subt
x2 = x1 * 4 # scaling by element size
x3 = K + x2 # byte address pointer arithmetic
x4 = *x3 # dereference to fetch K[d-e]
x5 = J + 24 # compute byte address of J[6]
*x5 = x4 # store into J[6] the value of K[d-e]
(请注意,三个地址代码从不重用临时变量,尽管在 MIPS 等效项中,对于临时结果(不再需要旧的临时值时)重用/重新调整寄存器用途是很常见的)。
此外,MIPS 可以在J[6]=
不单独计算的情况下进行J+24
,因此不必计算x5。
* 操作,C 操作符称为取消引用,当它发生在=
赋值的右侧时,它作为加载指令从内存中获取数据。当它出现在=
赋值的左侧时,这是作为将数据存储到内存中的存储指令完成的。
接下来,让我们看看地址计算以及 MIPS 可以做什么和不能做什么。
您对 有正确的想法$t3($s2)
,但 MIPS 无法做到这一点。它只能做常量索引。
那么,$t3($s2)
代表什么呢?它是动态索引与基地址的组合,产生了一个元素地址。
在这种(不支持的形式)中$t3($s2)
,这两个值$t3
和$t2
将如何组合?通过加法:我们可以为指针添加索引并获得一个新指针。
然而,因为 MIPS 是一个字节可寻址机器,MIPS 中的地址和指针是指单个字节。一个字节是一个 8 位的数据。所以,当我们在这样的机器上使用指针和地址时,这些地址和指针的类型是字节地址。
当我们使用 32 位字时,它们占用多个字节,实际上 4 x 8 位字节对于一个 32 位字。当一个 32 位是数组的元素时,该字占用 4 个字节,每个字节都有自己的字节地址,因此它也占用 4 个字节地址。
与整个数组有时由其起始地址(其索引 0)引用的方式类似,整个元素(4 个字节)由其最低字节的地址引用。从一个元素移动到下一个元素,意味着移动 4 字节地址。
因此,给定一个索引,我们将该索引转换为字节偏移量,在这种情况下,这称为缩放。比例因子与数组中元素的大小相同,这里是一个整数数组,因此每个元素 4 个字节。因此比例因子为 4。
所以,我们想要的更像是$t3*4($s2)
,当然 MIPS 也做不到。但是使用单独的指令,MIPS 可以乘以 4,MIPS 也可以将动态值加在一起。完成这些后,我们可以使用 MIPS 提供的常数系数解引用形式——带有附加标识,因为我们已经计算了完整的地址。
有两种方法可以做到K[i+1]
::
添加i
和1
,然后将该结果乘以 4,然后添加K
并使用零作为加载或存储指令中的偏移量。
乘以i
4,然后添加K
并使用 4 作为存储指令中的偏移量。
表格 2 使用非零偏移值 4,即按 *4 缩放的 +1。这恰好比解决方案 1 短 1 条指令。
如何乘以一个像 4 这样的小常数,假设要乘的数在 中$t0
,而结果是在 中$t1
:
add $t1, $t0, $t0 # t1 = t0 + t0 = t0 * 2
add $t1, $t1, $t0 # t1 = t1 + t0 = t0 * 3
add $t1, $t1, $t0 # t1 = t1 + t0 = t0 * 4
add $t1, $t0, $t0 # t1 = t0 + t0 = t0 * 2
add $t1, $t1, $t1 # t1 = t1 + t1 = t0 * 2 + t0 * 2 = t0 * 4
sll $t1, $t0, 2 # t1 = t0 << 2 = t0 * 4
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句