我想计算MIPS上列表的平均值。我尝试过隔离,如果我想打印出一个总和或者提示测试,它的效果非常好但是当我把平均计算重新放入时,它会以某种方式给我* 4作为答案。我的汇编代码如下:
.data
size_prompt: .asciiz "Enter number of elements: "
element_prompt: .asciiz "Enter an element: "
size: .word 0
to_store: .word 0
sum: .word 0
avg: .word 0
.text
#Prints prompt
la $a0, size_prompt
addi $v0, $0, 4
syscall
#Gets input from user
addi $v0, $0, 5
syscall
sw $v0, size
addi $t0, $0, 0 #Initialise i = 0
#Creates the list
lw $s0, size
addi $t1, $0, 4
mult $s0, $t1
mflo $t2
add $a0, $t1, $t2
addi $v0, $0, 9
syscall
stack: beq $t0, $s0, list_sum
la $a0, element_prompt
addi $v0, $0, 4
syscall
addi $v0, $0, 5
syscall
sw $v0, to_store
lw $t5, to_store
addi $sp, $sp, -4
sw $t5, 0($sp)
addi $t0, $t0, 1
j stack
list_sum: beq $s0, 0, average
lw $t6, sum
lw $t7, 0($sp)
addi $sp, $sp, 4
add $t6, $t7, $t6
sw $t6, sum
addi $s0, $s0, -1
j list_sum
average: lw $t0, sum
div $t0, $s0
mflo $t0
sw $t0, avg
lw $a0, avg
addi $v0, $0, 1
syscall
答案 0 :(得分:1)
好的,你只有 一个错误而且它是一个单行,所以你做得很好。
然而,代码中没有太多评论,因此当我阅读/分析它时,我添加了一些。
我应该提一下,当我这样做时,我能够通过视觉检查和审查发现错误。也就是说,我能够找到这个错误,然后单独使用修复程序对其进行注释。
所以,我实际上并不需要使用调试器来执行代码。应用此修复程序后,它第一次正确运行。
我最近在这里回答了一个非常类似的问题:MIPS questions about writing assembly to call functions on an array在数组上进行求和/产品
此外,请在此处查看我的答案:MIPS linked list除此之外,它还根据我自己的个人经验撰写了关于编写干净的mips / asm代码的指南。
我创建了两个版本的代码。一个只有最小的变化,只是错误修复。而另一个,我把它收紧并简化了一下。请原谅无偿的风格清理。
以下是包含错误/修复注释的代码:
.data
# NOTE/BUG: due to alignment issues put the .word directives _before_
# the [variable length] .asciiz directives
size: .word 0
to_store: .word 0
sum: .word 0
avg: .word 0
size_prompt: .asciiz "Enter number of elements: "
element_prompt: .asciiz "Enter an element: "
msg_space: .asciiz " "
.text
.globl main
main:
# Prints prompt
la $a0,size_prompt
addi $v0,$0,4
syscall
# Gets input from user
addi $v0,$0,5
syscall
sw $v0,size
addi $t0,$0,0 # Initialise i = 0
# Creates the list
lw $s0,size # get array count
addi $t1,$0,4 # get 4
mult $s0,$t1 # get count * 4
mflo $t2 # get offset
add $a0,$t1,$t2
addi $v0,$0,9
syscall
stack:
beq $t0,$s0,list_sum # done with number input? if yes, fly
# prompt user for list element
la $a0,element_prompt
addi $v0,$0,4
syscall
# read in element value
addi $v0,$0,5
syscall
sw $v0,to_store
lw $t5,to_store
# push element to stack
addi $sp,$sp,-4
sw $t5,0($sp)
addi $t0,$t0,1 # advance array index
j stack
# get sum of array elements
list_sum:
beq $s0,0,average # at end? if yes, fly
lw $t6,sum # get previous sum
lw $t7,0($sp) # get next array element value
addi $sp,$sp,4 # advance array pointer
add $t6,$t7,$t6 # sum += array[i]
sw $t6,sum # store it
addi $s0,$s0,-1 # bump down the _count_
j list_sum
# NOTE/BUG: in the list_sum loop above, s0 is being decremented, so when we
# get here it is _always_ zero
average:
lw $t0,sum # get the sum
# print the sum
li $v0,1
move $a0,$t0
syscall
# NOTE/FIX: restore the count value
lw $s0,size
div $t0,$s0 # divide by count
mflo $t0
sw $t0,avg # store average
li $v0,4
la $a0,msg_space
syscall
# print average
lw $a0,avg
addi $v0,$0,1
syscall
exit:
li $v0,10 # exit program
syscall
这是我对清理工作的看法。
mips有许多寄存器,所以当它们可以使用时,可以保留中间结果。
例如,请注意,在求和循环中,不同的寄存器用于递减,因此$s0
仍然存在。此外,我能够使用寄存器来保存以前使用内存位置的所有值[堆栈使用情况除外]
.data
size_prompt: .asciiz "Enter number of elements: "
element_prompt: .asciiz "Enter an element: "
msg_space: .asciiz " "
.text
.globl main
main:
# prompt user for number of elements
la $a0,size_prompt
li $v0,4
syscall
# get array count from user
li $v0,5
syscall
move $s0,$v0 # save array count
li $t0,0 # i = 0
stack:
beq $t0,$s0,sumlist # input done (i.e. i >= count)? if yes, fly
# prompt user for list element
la $a0,element_prompt
li $v0,4
syscall
# read in element value
li $v0,5
syscall
# push element to stack
addi $sp,$sp,-4
sw $v0,0($sp)
addi $t0,$t0,1 # i += 1
j stack
# get sum of array elements
# t6 -- sum value
sumlist:
li $t6,0 # sum = 0
move $t4,$s0 # get the count
sumlist_loop:
beqz $t4,average # at end? if yes, fly
# pop element off stack
lw $t7,0($sp) # get next array element value
addi $sp,$sp,4 # advance array pointer
add $t6,$t6,$t7 # sum += array[i]
addi $t4,$t4,-1 # bump down the count
j sumlist_loop
# get average
# t6 -- sum value
# t5 -- average value
average:
# print the sum
li $v0,1
move $a0,$t6 # get the sum
syscall
div $t6,$s0 # compute sum / count
mflo $t5 # retrieve it
# output a space
li $v0,4
la $a0,msg_space
syscall
# print average
move $a0,$t5
li $v0,1
syscall
exit:
li $v0,10 # exit program
syscall