2015-10-28 4 views
0

Мой код имеет две части; первая часть выполняет функцию, которая принимает два числа и возвращает их продукты. Я считаю, что я сделал эту часть правильно. Вторая часть, где я не уверен, в чем проблема. В этой части мне нужно сделать функцию, которая найдет факторный номер, и в рамках этой функции я должен использовать функцию умножения, которую я сделал в первой части. Пожалуйста, взгляните на мой код и скажите мне, что я делаю неправильно.Вложенная функция в MIPS

.data 
Fa_message: .asciiz "\nFAIL TEST\n" 
Pa_message: .asciiz "\nPASS TEST\n" 

number1: .word 4 
number2: .word 5 
KnownAnswers: .word 20 
START: .word 16 

.text 

main: 
# taking in the numbers for calculation. 
lw $a0, number1 # $a0 =4 
lw $a1, number2 # $a1 =5 
lw $t0, KnownAnswers # $t0 =20 

jal func_multiply # calling the mulyiply function 

move $t4,$v0  # store the product for any further comparisons  
bne  $t0, $t4, FailT # did it fail the test? 
beq  $t0, $t4, PassT # did it pass the test? 

func_multiply: # the mulyiply function 
mul $v0, $a0, $a1 # $v0 = number1 * number2 
jr $ra 

FailT: # print "\nFAIL TEST\n" 
li $v0,4 
la $a0, Fa_message 
syscall 

PassT: # print "\nPASS TEST\n" 
li $v0,4 
la $a0, Pa_message 
syscall 

###---------------------(PART-2)------------------- 

lw $a0, number1 # load the number for the factorial procedure 
beq $a0, $zero, factorialDone # (if the number = 0), !0 = 1 
mul $a1, $a1, $zero # initializing $a1 
mul $a2, $a1, $zero # initializing $a2 
addi $a1, $a0, -1 # $a1 = (the entered number - 1) 
addi $a2, $a0, 0 # $a2 = the entered number 
jal findfactorial 
### 

#Stop 
li $v0, 10 
syscall 


    findfactorial: 


    jal func_multiply # calling the mulyiply function # mul $v0, $a0, $a1 # $v0 = number1 * number2 
    move $t4,$v0  # store the product in t4 for any further usage 
    addi $a0, $a0, -1 # $a1 = $a1-1 
    addi $a1, $a0, -1 
    bne $a1, $zero, findfactorial # enter a loop if $a1 does not equal 0 



    jr $ra 

    factorialDone: 
    addi $v0, $v0, 1 
    syscall 

ответ

0

jal инструкция изменяет $ra регистр. Поэтому, если функция A вызывает функцию B, тогда A должен сохранить и восстановить значение, которое $ra было при вводе A, чтобы оно могло вернуться в нужное место. Обычно это делается с использованием стека в качестве временного хранилища.

Вы можете нажать регистр в стеке (сохранить), как это:

addi $sp, $sp, -4 
sw $ra, ($sp) 

И совать регистр из стека (восстановить его), как это:

lw $ra, ($sp) 
addi $sp, $sp, 4 

Тогда есть ваша петля . Вы отбрасывая результат всех предыдущих итераций, так что ваш результат всегда будет 1 * 2 == 2. Цикл должен выглядеть примерно так:

findfactorial: 
    jal func_multiply 
    move $a0,$v0 
    addi $a1, $a1, -1 
    bne $a1, $zero, findfactorial 

Таким образом, вы первый умножить 4 на 3, затем 12 на 2 и т. д.


В вашем коде есть некоторые другие символы. Например, если вы переходите на FailT, вы не сразу выходите из программы после печати сообщения - вы просто продолжаете выполнять код после PassT.

Кроме того, я не уверен, что это должен делать:

factorialDone: 
addi $v0, $v0, 1 
syscall 

Если вы хотите, чтобы выполнить системный вызов 1 (print_int), то это неправильно, потому что он не настроен должным образом $v0 (его должен быть li $v0,1). И если вы хотите, чтобы это напечатало результат ваших факториальных вычислений, тогда этого не произойдет, потому что у вас есть jr $ra прямо перед этим, так что единственный раз, когда вы закончите с factorialDone, - это если number1 содержит 0. Также у вас будет для настройки $a0 со значением, которое вы хотите распечатать.