2012-04-07 61 views
1

我试图编写一个MIPS程序,它获取一个无符号整数作为参数,并以递归方式返回整数中所有小数位的和。例如,如果参数是75080,则返回的总和是20(7 + 5 + 0 + 8 + 0)。这是我的代码到目前为止。任何帮助,将不胜感激。MIPS递归

我的想法是将数字除以10,留下数字中的最后一个整数,使用mfhi添加提醒。

.data 
prompt: .asciiz "Enter a string of integer: " 
output: .asciiz "\nThe total sum is: " 
    .text 
    .globl main 
main: 
    la $a0, prompt 
    li $v0, 4 
    syscall 

    li $v0, 5 
    syscall 

    move $t2, $v0 

    la $a0, output 
    li $v0, 4 
    syscall 

Loop: 
    div $t2, $t2, 10 
    mflo, $t1 
    mfhi, $t3 
    beqz $t1, Exit 
    add $t1, $t1, 0 
    b additive 

additive: 
    add $t0, $t1, $t1 
    j Loop 

Exit: 
     la $a0, output 
      li $v0, 4 
      syscall 
      la $v0, 10 
      syscall 
+0

什么操作系统是这个地方的系统调用4让您打印的提示没有给出一个缓冲区长度,和系统调用5让你这已经转换为一个整数输入? – Kaz 2012-04-07 06:21:02

+0

我不记得MIPS是否是这种方式,但在某些系统中,重要的是从高位移动到低位命令的顺序进来,如果我记得有关MIPS的事实上是正确的,那么您可能已经获得了这倒退了。 – 2012-04-07 06:44:49

+0

这是http://stackoverflow.com/questions/10031785/iteration-and-recursive-in-mips的转贴 – bta 2012-04-10 17:53:30

回答

0
  • 这是什么应该做的事情?添加0到寄存器将不会改变它的值:

    add $t1, $t1, 0

  • 分裂和复制到$t1$t3,该$t1后和其余$t3。当你添加到总数中时,你会以相反的方式处理它。

  • 这实际上会给你$t0 = 2 * $t1:你正在给自己加$t1并将结果存储在$t0

    add $t0, $t1, $t1

    你可能真的想:

    add $t0, $t0, $t3

  • 你检查$t1 == 0之前加入其余总,所以最显著位永远不会增加。你并不需要增加一个子程序。您也可以使用bnez Loop而不是beqz Exit - >b Loop。最后,你甚至不需要$t1,因为商已经在$t2

摆脱additive和替换Loop本:

Loop: 
    div $t2, $t2, 10 
    mfhi, $t3 
    add $t0, $t0, $t3 
    bnez $t2, Loop 
  • Exit是怪异:你打印的output字符串第二次,而不是打印整数。

它改成这样:

Exit: 
    move $a0, $t0 
    la $v0, 1 
    syscall 

    la $v0, 10 
    syscall 
0

的方法是相当简单的。您需要递归函数,我将它命名为SumDigits,它将采用参数中所有数字的最后一位数字和重复过程。递归调用返回后,您将向前一个结果添加数字。该代码评论为更容易理解。代码如下:

.text 

#calculates sum of digits recursively 
SumDigits: 

    sub  $sp, $sp, 12     #alloocate 12B on stack 
    sw  $ra 0($sp)      #save return address 
    sw  $a0, 4($sp)      #save argument 

    beq  $a0, $0, exit_sumdigits  #when there is no more digits return 0 
    rem  $t0, $a0, 10     #get last digit 
    sw  $t0, 8($sp)      #save it on stack 
    div  $a0, $a0, 10     #divide argument by 10 
    jal  SumDigits      #repeat procedure 
    lw  $t0, 8($sp)      #read digit from stack 
    add  $v0, $v0, $t0    #add digit to previous result 
    lw  $ra, 0($sp)      #load return address 
    addi $sp, $sp, 12     #free stack 
    jr  $ra        #return 

exit_sumdigits: 
    li  $v0, 0       #there are no more digits, return 0 
    lw  $ra, 0($sp)      #load return address 
    addi $sp, $sp, 12     #free stack 
    jr  $ra        #return 

main: 
    li  $a0, 75080      #load number in $a0 
    jal  SumDigits       #call SumDigits 

    move $a0, $v0       #set a0 = result of SumDigits 
    li  $v0, 1       #set $v0 for print int system call 
    syscall 

    li  $v0, 10       #set $v0 for exit system call 
    syscall 

.data