2012-04-07 2 views
1

Я пытаюсь написать программу MIPS, которая получает целое число без знака в качестве аргумента и возвращает сумму всех десятичных цифр в целочисленном рекурсивно. Например, если аргумент равен 75080, тогда возвращаемая сумма равна 20 (7 + 5 + 0 + 8 + 0). Вот мой код до сих пор. Любая помощь будет оценена по достоинству.MIPS, Recursion

Мой образ мышления состоял в том, чтобы разделить число на 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

Какая ОС это, когда syscall 4 позволяет распечатать приглашение без указания длины буфера, а syscall 5 получает вход, который уже преобразован в целое число? – Kaz

+0

Я не помню, является ли MIPS таким способом или нет, но в некоторых системах имеет значение, в каком порядке происходит переход с высокого уровня и переход от низких команд, и если что-то, что я помню о MIPS, действительно правильно, вы, возможно, получили это назад. –

+0

Это сообщение http://stackoverflow.com/questions/10031785/iteration-and-recursive-in-mips – bta

ответ

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