我想计算MIPS上列表的平均值

时间:2016-08-08 15:03:04

标签: assembly mips mars-simulator

我想计算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

1 个答案:

答案 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