我不明白为什么递归调用的结果与迭代方式不同。(MIPS代码)

问题描述 投票:0回答:1

我是 MIPS 的初学者。 我必须编写一个具有多个条件的 MIPS 代码。

  1. 从控制台获取正整数n
  2. 以迭代方式(使用循环)和递归方式(使用递归调用)计算从 1 到 n 的总和
  3. 然后在控制台打印出结果。
  4. 我必须将它们写在一个代码上。

所以,我在这段代码上写了,这段代码在递归调用上提供了错误的结果。 迭代方式和递归方式的结果一定是相同的,但事实并非如此。

我发现这段代码存在一些问题。 我想我必须写它们 $a0, $t0 但每当我写这个的时候。递归调用的结果不会打印在控制台上。

这是我的代码。

.数据 整数:.asciiz " 输入一个正整数:“ result_1: .asciiz "(迭代)从 1 到 n 的总和:" 结果_2:.asciiz“ (递归)从 1 到 n 的和:“ 换行符:.asciiz " ”

.文本 主要的: li $v0, 4 la $a0,整数 系统调用

    read_input:
        li $v0, 5
        syscall
        move $t0, $v0  

        # Calculate the sum iteratively
        li $t1, 0   # Initialize sum to 0
        li $t2, 1   # Initialize the counter to 1

        loop_iterative:
            add $t1, $t1, $t2   # Add counter to sum
            addi $t2, $t2, 1     # Increment the counter

            # Check if the counter is less than or equal to n
            ble $t2, $t0, loop_iterative
            
        
        #Call the recursive function to calculate the sum 
        move $a0, $s0
        jal calculate_sum       
        
        # Print a newline
        li $v0, 4
        la $a0, newline
        syscall
                
        # Print the result_1
        li $v0, 4
        la $a0, result_1
        syscall

        move $a0, $t1
        li $v0, 1
        syscall
        
        # Print the result_2
        li $v0, 4
        la $a0, result_2
        syscall

        move $a0, $v0
        li $v0, 1
        syscall

        # Print a newline
        li $v0, 4
        la $a0, newline
        syscall

        # Exit the program
        li $v0, 10
        syscall
        
calculate_sum:
    #Recursive function to calculate the sum
    #Input: $a0-n
    #Output: $v0-sum
    
    #if n<=1, return 1
    blez $a0, calculate_sum_base
    li $v0,0
    
calculate_sum_loop:
    add $v0, $v0, $a0
    addi $a0, $a0, -1
    blez $a0, calculate_sum_end
    jal calculate_sum_loop
    
calculate_sum_base:
        li $v0, 1
        
    calculate_sum_end:
        jr $ra
recursion sum iteration mips
1个回答
0
投票

您使用

$v0
违反了调用约定。

这是返回值的寄存器,但您希望它能够在递归调用中幸存下来 - 但它不会。

您需要执行以下操作之一:

  • 在递归调用后进行加法,保存原始的 $a0,因为它会被调用擦除。

  • 使用/发明一种非标准调用约定,不会在每个递归级别重置答案。

建议回到 C/高级语言版本的递归方法并尝试最准确地复制它。这可能是从这个练习中了解你应该学到什么的最好方法。虽然没有显示怀疑会像第一个选择。

© www.soinside.com 2019 - 2024. All rights reserved.