array[i]%2 和来自程序集中用户的值

array[i]%2 and value from the user in assembly

我需要用 MIPS 编写这段代码:

int i, size, result = 0;
int * array;
...
//size gets a value from the user
//array is allocated according to this value
...
for ( i=0;i<size;i++ )
{
if (array[i] %2 ==0) // if array[i] is even
result += array[i]; // add it to the result
}

and使用的寄存器是$s1表示i,$s2表示size,$s3表示起始地址 数组,$s4 表示结果。

我写了:

ori $s1,[=11=],0  // int i
ori $s3,array // int array *
add $s4,$zero,$zero  // int result = 0;

l1:
bge $s1,$s2,Done // for loop i<size
...
lw , 0($s3) //  = array[I]
addu $s4,$s4,$s5 // result += array[I]
j UPDATE

UPDATE:
addi $s1, $s1, 1 // i++
addi $s4, $s4, 4 // move array pointer
j L1 // goto l1

DONE:
nop

我不知道怎么写 2 件事:

  1. if (数组[i] %2 ==0)
  2. size 从用户那里得到一个值 请帮我处理这些事情。 谢谢

所以我现在写了:

ori $s1,[=12=],0  // int i
li   $v0, 5 // scan int from user
la $s3,array // int array *
add $s4,$zero,$zero  // int result = 0;

l1:
bge $s1,$s2,Done // for loop i<size
lw $s5, 0($s3) // $s5 = array[I]
add $s6,$zero,$s5 // $s6 = $s5
mov $s6, 31 
and $s7,$s6,1
bne $s7, $zero, ADDING
j UPDATE

ADDING:
addu $s4,$s4,$s5 // result += array[I]
j UPDATE

UPDATE:
addi $s1, $s1, 1 // i++
addi $s4, $s4, 4 // move array pointer
j L1 // goto l1

DONE:
nop

建议您从一些工作示例开始:那里有很多 MIPS 示例。

但是,您有 C 代码并在 MIPS 中遵循它,这是一个非常好的方法。


首先,建议您将数组声明为全局数组,也许您已经声明了,但没有显示出来。


这条指令ori $s3,array // int array *需要是一个la操作码,代表“加载地址”(对于MARS或QtSpim)。这些会将标签的地址加载到寄存器中。


array[i] 是通过将 i 从索引缩放到字节偏移量,然后将该字节偏移量添加到 array 的字节地址,最后取消引用该指针来实现的。由于数组的每个元素占用 4 个字节,并且在字节寻址机器上,每个单独的字节都有自己的地址,因此下一个数组元素在内存中是 4 个地址。因此,索引 0 位于数组地址,但索引 1 位于数组 + 4。我们在 C 中看不到这种缩放,因为它知道类型(它知道元素大小为 4,所以 +1 表示 +4)并且确实自动缩放。

因此,我们将 i 缩放(即乘以)4,因为 4 是 2 的幂,通常通过向左移动 2 位来完成。移位就像乘以 10,但它是二进制而不是十进制,因此实际上乘以 2。移位两次乘以 100 二进制,因此乘以 4 位十进制。当然MIPS可以1条指令移位2位

要进行这种转换,您需要选择一个未使用的寄存器来保存中间结果,即字节偏移量。建议使用 $t 寄存器来获取这些短暂的临时值。

然后将该中间结果添加到数组基址的字节地址,这里是 $s3(也许还将该结果发送到另一个未使用的寄存器)。

现在可以像使用 lw , 0($s3) // = array[I] 一样取消引用新的中间值,除了将索引计算作为基地址而不是 $s3


在循环之前的开始,你还需要用大小初始化$s2


以下结构无害但也无用:

j UPDATE

UPDATE:

如果对您有帮助,您可以留下标签,但不需要从紧接在前面的指令中删除,因为处理器会自然地这样做。

需要说明的是,标签是用于汇编代码的,但它们已被汇编程序删除,不会出现在机器代码中。处理器只在执行机器代码指令时做事。每条指令都告诉处理器下一步要执行什么指令,因此 addu $s4,$s4,$s5 // result += array[I] can/will 告诉处理器执行 addi $s1, $s1, 1 // i++ 而无需 j.


注意以下拼写错误:

lw , 0($s3) //  = array[I]
addu $s4,$s4,$s5 // result += array[I]

第一行应该指定 $s5 而不是允许的 </code>,而是不同的寄存器 (<code>$a1)。 (我会为该中间结果使用 $t 寄存器而不是 $s 寄存器,但没关系。)


您可以通过除法或更简单的检查低位来完成 %2。 C 表达式将是 & 1,如 array[i] & 1。由于在二进制中低位位置表示 20,因此这是检查 even/odd 的方法(0 位位置是 2 的唯一奇次方)。 MIPS 可以在一条指令中完成该屏蔽。 1 作为掩码表示仅保留另一个操作数 (array[i]) 的低位。

== 0,因为它是条件操作的一部分,其执行方式类似于 for 循环退出条件的 bge


要从 MARS 中的用户那里获取号码,请使用系统调用 # 5。按照 help 中的说明或此处或其他地方的许多在线示例进行操作。