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 件事:
- if (数组[i] %2 ==0)
- 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 中的说明或此处或其他地方的许多在线示例进行操作。
我需要用 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 件事:
- if (数组[i] %2 ==0)
- 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 中的说明或此处或其他地方的许多在线示例进行操作。