【问题标题】:Calculate the total sum of all elements in an integer array in MIPS计算 MIPS 中整数数组中所有元素的总和
【发布时间】:2021-10-12 05:59:03
【问题描述】:

我需要帮助来计算整数数组中所有元素的总和。 我似乎无法循环工作。 如果您不提出基于“请勿更改或使用此行下方的任何内容”下方的更改的解决方案,我将不胜感激。

预期结果:

11个整数的和是217

当前和不正确的结果:

11个整数之和为11

代码sn-p:

##############################################################################
# DESCRIPTION:  Calculates the total sum of all elements in an integer array
#
# INPUT:        $a0 - The address of the first number in the array
#               $a1 - Number of integers stored in the array
#
# OUTPUT:       $v0 - The sum of all numbers in the integer array
##############################################################################
           .text
        j   main

int_array_sum:

##  Clues:
##  - Do not forget to clear registers that do not have an edge content
##  - An integer corresponds to 4 bytes of memory. Each integer is thus 32 bits
##  - If you want to multiply the contents of a register with an even two-power, 
##    a common trick (hint) is to shift bits a few steps left.
##    Example (verify with pen and paper. sll = Shift Left Logical):
##    sll $t1, $t0, 2     #    $t1 = $t0 * 4
##    sll $t0, $t1, 4     #    $t0 = $t1 * 16

#pseudocode:
    # If $t0 (i) is = $a1 skip to end_int       # Done if i == N
    # Multiply $t0 by 4 and store it in $t1     # Indexadr = i * 4
    # Add $t1 with $a0 and save in $t2          # Address = $a0 + Indexadr
    # Retrieve the number from memory that $t2 points to and store in $t3    # n = A [i]
    # Add $t3 to $v0 (results register)         # Sum = Sum + n
    # Add 1 to register $t0                     # i = i + 1
    # Skip to for_every_int

#### WRITE YOUR ASSEMBLY CODE HERE ####
    li  $v0, 0
    li  $t0, 0
loopA:
    #If $t0 (i) is = $a1 skip to end_int
    beq $t0, $a1, end_int   # Done if i == N
    
    # Multiply $t0 by 4 and store it in $t1
    sll $t1, $t0, 2     # Indexadr = i * 4
    
    #Add $t1 with $a0 and save in $t2 
    add $t2, $t1, $a0       # Address = $a0 + Indexadr  
    
    #Retrieve the number from memory that $t2 points to and store in $t3
    lb $t3, 0($t2)          # Load the number from array # n = A [i]
    
    #Add $t3 to $v0 (results register)
    addu $v0, $v0, $t3      # Sum = Sum + n
    
    #Add 1 to register $t0
    add $t0, $t0, 1         # i = i + 1
    
    #Repeat
    j loopA
end_int:
        jr      $ra      # Return to calling code

##############################################################################
##############################################################################
##
##    *** Don't change or use ANYTHING below this line. 
##
##############################################################################
##############################################################################

### Data that is being used as main program

    .data
    
INT_COUNT:
    .word       11
INT_ARRAY:
    .word       1, 3, 6, 9, 2, 4, 6, 8, 10, 55, 113

INT_1_str: 
    .asciiz "Sum of the " 
INT_2_str:
    .asciiz " integer is " 

    .text
    .globl main
##############################################################################
#
# MAIN: Calls subroutine and prints the results
#
##############################################################################  
main:
    ##---
    ### int_array_sum
    ##---
    li      $v0, 4
    la      $a0, INT_1_str
    syscall                            # print string

    lw      $a0, INT_COUNT
    li      $v0, 1
    syscall                            # print integer

    li      $v0, 4
    la      $a0, INT_2_str
    syscall                            # print string
    
    li      $v0, -1
    la      $a0, INT_ARRAY
    lw      $a1, INT_COUNT
    jal     int_array_sum         # run subroutine

    # Print sum
    add     $a0, $v0, $zero
    li      $v0, 1
    syscall                            # print integer (array sum)
    
###--- EXIT
    li      $v0, 10                # MARS / SPIM exit
    syscall
    
#### EOF #####################################################################  

【问题讨论】:

    标签: assembly integer mips calc


    【解决方案1】:

    如果你要学习汇编语言,你应该掌握基本的调试技能。

    通过 StackOverflow 调试程序是一项挑战——调试是一种交互式活动,而 StackOverflow 并不真正符合这种形式!

    所以,以下是一些思考过程。

    您可以向前调试到错误或意外结果,也可以从错误或意外结果向后调试。

    第一次运行新代码时,我更喜欢继续。单步并检查每条指令是否符合您的预期。如果任何一条指令所做的事情与您的预期不同,那么这就是重点所在。在寻找与预期的差异时,既要查看指令的寄存器效应,也要查看内存效应,并遵循预期的控制流程。

    回过头来,我们可能会问:0x00400088 处的指令是什么?为什么它访问位置0x10400000?要回答这个问题,您必须向后工作,看看是什么指令创建了该内存地址,然后确定出错的原因以及需要什么。

    前进通常比后退更容易,尤其是对于可能出现拼写错误的新代码 b/c 如果您有多个错误,处理第一个比处理最后一个要少 - 最后一个可能无法工作 b /c 早期的错误/错别字是复合的,而向前工作,除非你错过了什么,否则不会有复合的错误。

    有时,编写一个更简单的程序并将这些简单的部分放在一起比编写一个完整的程序并对其进行调试更容易。所以,试着把整体分解成更小的部分,让每个更小的部分发挥作用,然后将这些更小的解决方案组合成一个更大的整体。

    如果您遇到循环问题,您可能会从最简单的循环程序开始,如果您遇到问题,那么您可能会就遇到问题的指令提出技术问题。

    【讨论】:

    • 我已经编辑了代码并上传了不会崩溃的新代码:)
    【解决方案2】:

    好的,所以您已经修复了崩溃并更新了问题以询问您的最新问题,即您不尊重参数和返回值的传递。

    这改变了问题的性质,就像我说的,调试是一种不适合 StackOverflow 的交互式活动。通常不赞成完全改变问题帖子的性质,以至于先前的答案不再相关。在这种情况下,最好发布一个新问题而不是编辑现有问题。如果可以增加现有问题的清晰度,则可以编辑现有问题。

    不过,请重新阅读作业顶部的注释/注释,其中指出$a0$a1 中的输入参数和输出返回值在$v0 中:

    ##############################################################################
    # DESCRIPTION:  Calculates the total sum of all elements in an integer array
    #
    # INPUT:        $a0 - The address of the first number in the array
    #               $a1 - Number of integers stored in the array
    #
    # OUTPUT:       $v0 - The sum of all numbers in the integer array
    ##############################################################################
    

    这样做而不是使用替代寄存器 - 也不要为输入参数提供初始化器 - 这些输入参数由 main 初始化,因为传递输入参数的整个想法是调用者提供值!

    进一步,让我们继续观察main 中紧邻函数调用的代码,并看到它提供了输入参数并查找输出返回值,如赋值的相同初始注释中所述。

        li      $v0, -1               # clearing answer register, let the sub provide proper value
        la      $a0, INT_ARRAY        # passing first parameter
        lw      $a1, INT_COUNT        # passing second parameter
        jal     int_array_sum         # run subroutine
    
        # Print sum
        add     $a0, $v0, $zero       # expecting return value in $v0
        li      $v0, 1
        syscall                       # print integer (array sum)
    

    (现在,你为什么认为总和是-1?)


    好的,让我们从上面的main 的作用开始。首先它清除(好吧,设置为-1)结果寄存器。

    然后main 将 INT_ARRAY 的地址放入 $a0 并将值 11 放入 $a1 — 这是您的两个输入参数,因此您应该在函数中使用它们。

    暂时使用这个main 代码,您会注意到,在从函数调用返回时,此代码需要$v0 中的函数输出/返回值,但由于$v0 未从-1 修改main 清除它,这就是打印的内容(您的代码未能在 $v0 中返回正确的值。

    好的,现在考虑到main 的工作方式(以及根据输入/输出描述),您的函数的设置是 INT_ARRAY 指针位于$a0 寄存器中 - 已作为参数传递给 @ 987654340@ — 它在函数的最顶部,甚至在函数的第一行函数代码之前都有这个正确的值。

    好的,所以无论何时你需要数组指针,使用$a0而不是你的$t0 - 并注意它已经预先初始化,所以只需使用 ,无需通过一些 la 指令进一步启动。

    此外,您需要用于输出/返回值的寄存器是$v0,因此在需要时使用$v0 而不是$t3引用 sum 变量,当您返回给调用者时,sum 值将在调用者期望的 $v0 中。

    接下来,用寄存器$a1替换常量值11;这是保存main 提供给您的长度参数的寄存器。

    【讨论】:

    • 感谢您帮助我。我还是不明白。
    • 我在这个答案中添加了一些特定的文本,关于如何更改您的寄存器以使函数调用正常工作。
    • 这样? loopA: # 条件到终端循环 beq $t0, $a1, end_int sll $t0, $t1, 2 addu $t2, $t1, $a0 addiu $t3, $t2, 4 addi $t3, $v0, 11 addi $ t0, $v0, 1 j 循环A
    • 您进行了太多更改。一方面,循环中没有lw,因此它不再访问内存。 beq 没问题,但循环中根本不应该有 11,因为该值取自输入参数。你可以从你以前的内容开始,只改变我所说的:$t0 -> $a0,和$t3 -> $v0,和11 -> $a1
    • 我更新了问题中的代码,请指导我到正确的路径并告诉我代码中的错误。
    猜你喜欢
    • 2019-09-26
    • 1970-01-01
    • 2021-07-19
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多