这是我的代码,我无法获得正确的输出。我哪里错了?我将min设置为零,然后检查数组是否小于或等于此值,然后如果是,我跳转到标签并将min的值设为数组的值,然后跳回到迭代数组。
$_SERVER
答案 0 :(得分:4)
好的,我发现了几个漏洞。我创建了三个版本,并添加了输出系统调用,以便您可以看到结果[请原谅无偿的样式清理]:
以下是您的原始代码,其中包含错误注释:
.data
xyz: .word -8,16,-32,64,-128,256
# int main(void)
#
# local variable register
# int *p $s0
# int *end $s1
# int min $s2
# int total $s3
#
.text
.globl main
main:
la $s0,xyz # p = foo
addi $s1,$s0,24 # end = p + 6
add $s3,$zero,$zero # total = 0
# NOTE/BUG: to find minimum, you want to init this to the first array
# element
# also, initializing with a minimum value (e.g. 0), or more correctly, the
# largest possible negative number (e.g. 0x80000000) implies a search for
# maximum
add $s2,$zero,$zero # min = 0
L1:
beq $s0,$s1,L2 # if (p == end) goto L2
lw $t0,($s0) # $t0 = *p
# NOTE/BUG: s2 is a register variable that contains "min" (e.g. int min)
# and is _not_ a pointer to a "min" variable in memory (e.g. int *min)
lw $t1,($s2) # $t1 = min
# NOTE/BUG: the the check should be reversed:
slt $t2,$t1,$t0 # check if min is less than p
add $s3,$s3,$t0 # total += $t0
bne $t2,$zero,L3 # if min is less than p, go to L3
# NOTE/BUG: this pointer increment is out of place (i.e. it does not
# get incremented if there is a jump to L3)
# this won't affect the min value, but it will double count the value in
# the total
addi $s0,$s0,4 # p++
j L1
L2:
add $v0,$zero,$zero # return value from main = 0
jr $ra
L3:
move $s2,$t0
j L1
这是一个固定版本:
.data
xyz: .word -8,16,-32,64,-128,256
msg_min: .asciiz "min: "
msg_tot: .asciiz " total: "
msg_nl: .asciiz "\n"
# int main(void)
#
# local variable register
# int *p $s0
# int *end $s1
# int min $s2
# int total $s3
#
.text
.globl main
main:
la $s0,xyz # p = foo
addi $s1,$s0,24 # end = p + 6
add $s3,$zero,$zero # total = 0
lw $s2,0($s0) # min = xyz[0]
L1:
beq $s0,$s1,L2 # if (p == end) goto L2
lw $t0,0($s0) # $t0 = *p
addi $s0,$s0,4 # p++
add $s3,$s3,$t0 # total += $t0
slt $t2,$t0,$s2 # *p < min?
bne $t2,$zero,L3 # yes, fly
j L1
L2:
li $v0,4
la $a0,msg_min
syscall
li $v0,1
move $a0,$s2 # get min value
syscall
li $v0,4
la $a0,msg_tot
syscall
li $v0,1
move $a0,$s3 # get total value
syscall
li $v0,4
la $a0,msg_nl
syscall
# exit program
li $v0,10
syscall
L3:
move $s2,$t0 # set new/better min value
j L1
这是一个稍微清理过的版本,我颠倒了分支的感觉,并且能够收紧循环。此外,我更改了标签以更具描述性/功能:
.data
xyz: .word -8,16,-32,64,-128,256
msg_min: .asciiz "min: "
msg_tot: .asciiz " total: "
msg_nl: .asciiz "\n"
# int main(void)
#
# local variable register
# int *p $s0
# int *end $s1
# int min $s2
# int total $s3
#
.text
.globl main
main:
la $s0,xyz # p = foo
addi $s1,$s0,24 # end = p + 6
add $s3,$zero,$zero # total = 0
lw $s2,0($s0) # min = xyz[0]
main_loop:
beq $s0,$s1,main_done # if (p == end) goto L2
lw $t0,0($s0) # $t0 = *p
addi $s0,$s0,4 # p++
add $s3,$s3,$t0 # total += $t0
slt $t2,$s2,$t0 # *p < min?
bne $t2,$zero,main_loop # no, loop
move $s2,$t0 # set new/better min value
j main_loop
main_done:
li $v0,4
la $a0,msg_min
syscall
li $v0,1
move $a0,$s2 # get min value
syscall
li $v0,4
la $a0,msg_tot
syscall
li $v0,1
move $a0,$s3 # get total value
syscall
li $v0,4
la $a0,msg_nl
syscall
# exit program
li $v0,10
syscall
<强>更新强>
感谢帮助很多,但
lw $t1,($s2)
不起作用,因为lw只能用于指针?
右。请注意您使用s3
保留total
的方式。这就是代码使用s2
来保持min的方式。我[部分]这样做是因为最高评论:
# int min $s2
要使用lw
,最高评论应为:
# int *min $s2
要以原始方式使用s2
,您需要以下内容:
min: .word 0
并且,您需要(在循环开始之前):
la $s2,min
并且,您必须lw
和sw
,这只会减慢速度。因此,除了已经存在的内容之外,您还需要额外添加lw
和额外sw
。
mips有一个很多的寄存器[强项]。因此,它会加快速度,以便在其中保留自动的函数范围变量。
但是,为了完整起见,这是一个允许lw
使用它的版本。注意额外的内存访问。它很像用-O0编译的C代码:
.data
min: .word 0
xyz: .word -8,16,-32,64,-128,256
msg_min: .asciiz "min: "
msg_tot: .asciiz " total: "
msg_nl: .asciiz "\n"
# int main(void)
#
# local variable register
# int *p $s0
# int *end $s1
# int *min $s2
# int total $s3
#
.text
.globl main
main:
la $s0,xyz # p = foo
addi $s1,$s0,24 # end = p + 6
add $s3,$zero,$zero # total = 0
la $s2,min # point to min
lw $t4,0($s0) # fetch xyz[0]
sw $t4,0($s2) # store in min
main_loop:
beq $s0,$s1,main_done # if (p == end) goto L2
lw $t0,0($s0) # $t0 = *p
addi $s0,$s0,4 # p++
add $s3,$s3,$t0 # total += $t0
lw $t4,0($s2) # fetch min
slt $t2,$t4,$t0 # *p < min?
bne $t2,$zero,main_loop # no, loop
sw $t0,0($s2) # store new/better min value
j main_loop
main_done:
li $v0,4
la $a0,msg_min
syscall
li $v0,1
lw $a0,0($s2) # get min value
syscall
li $v0,4
la $a0,msg_tot
syscall
li $v0,1
move $a0,$s3 # get total value
syscall
li $v0,4
la $a0,msg_nl
syscall
# exit program
li $v0,10
syscall