[英]Recursivity in MIPS - Pascal triangle
我正在做一個Pascal Triangle來練習MIPS,但是當我必須執行遞歸函數時,我的代碼就會中斷。 我不知道要做代碼中標記的return語句:
首先,我將顯示我正在翻譯的C代碼,最后,您可能會看到沖突的return語句(已標記)
// C Language
#include <stdio.h>
int trianguloPascal(int i, int k);
int main(void) {
int num, i, j, k;
printf("Introduce el número de filas: ");
scanf("%i", &num);
for (i = 0; i < num; i++) {
for (j = num; j > i; j--) {
printf(" ");
}
for (k = 0; k <= i; k++) {
printf("%6d", trianguloPascal(i, k));
}
printf("\n");
}
return 0;
}
int trianguloPascal(int i, int k) {
if ((i == 0) || (k == 0) || (i == k)) {
return 1;
} else {
///////////////////////////////////
// THIS IS THE CONFLCTING RETURN //
///////////////////////////////////
return (trianguloPascal(i-1, k-1) + trianguloPascal(i-1, k));
}
}
現在,我將顯示MIPS代碼,最后,您在嘗試執行此沖突的return語句時會看到沖突(已標記)
// MIPS Languaje
.data
var_i: .word 0
var_j: .word 0
var_k: .word 0
var_num: .space 4
msg_pedirNumeroFilas: .asciiz "Introduce el número de filas: "
msg_espacioCorto: .asciiz " "
msg_espacioLargo: .asciiz " "
msg_saltoDeLinea: .asciiz "\n"
.text
# Función principal del programa
MAIN:
# Mostrar el mensaje de pedir un número de filas
la $a0, msg_pedirNumeroFilas # Cargamos la cadena de texto que vamos a mostrar
li $v0, 4 # Cargar en $v0 la llamada al sistema para 'Mostrar String'
syscall # Ejecutar la llamada al sistema
# Recoger el número de filas que desea el usuario
li $v0, 5 # Cargar en $v0 la llamada al sistema para 'Recoger Int'
syscall # Ejecutar la llamada al sistema
# Guardar en memoria el número de filas obtenido
sw $v0, var_num # Guardar en 'num' el número recogido anteriormente
# Cargamos de memoria las variables, almacenándolas en variables salvadas
lw $s0, var_i # Guardamos en $s0 la variable var_i
lw $s1, var_j # Guardamos en $s1 la variable var_j
lw $s2, var_k # Guardamos en $s2 la variable var_k
lw $s3, var_num # Guardamos en $s2 la variable var_num
# Guardamos en pila los valores de i, j, k, num
addi $sp, $sp, -16
sw $s0, 0($sp)
sw $s1, 4($sp)
sw $s2, 8($sp)
sw $s3, 12($sp)
# for (i = 0; i < num; i++)
li $s0, 0 # i = 0 para cada inicio del bucle FOR_I
FOR_I:
bge $s0, $s3, END_FOR_I # (i >= num) ? GOTO END_FOR_I : CONTINUE
# for (j = num; j > i; j--) {
move $s1, $s3 # j = num para cada inicio del bucle FOR_J
FOR_J:
ble $s1, $s0, END_FOR_J # (j <= i) ? GOTO END_FOR_J : CONTINUE
# Imprimir los espacios
la $a0, msg_espacioCorto # Cargamos la cadena de texto que vamos a mostrar
li $v0, 4 # Cargar en $v0 la llamada al sistema para 'Mostrar String'
syscall # Ejecutar la llamada al sistema
addi $s1, $s1, -1 # j -= 1
j FOR_J # Volvemos al bucle FOR_J
END_FOR_J:
# for (k = 0; k <= i; k++) {
li $s2, 0 # k = 0 para cada inicio del bucle FOR_K
FOR_K:
bgt $s2, $s0, END_FOR_K # (k > i) ? GOTO END_FOR_K : CONTINUE
# Imprimir los espacios
la $a0, msg_espacioLargo # Cargamos la cadena de texto que vamos a mostrar
li $v0, 4 # Cargar en $v0 la llamada al sistema para 'Mostrar String'
syscall # Ejecutar la llamada al sistema
# Llamada a la función recursiva
move $a0, $s0 # Pasar como primer agumento i
move $a1, $s2 # Pasar como segundo agumento k
jal TRIANGULO_PASCAL # Llamada a triangulo_pascal(i, k)
# Imprimir resultado devuelto
move $a0, $v0 # Cargamos la cadena de texto que vamos a mostrar
li $v0, 1 # Cargar en $v0 la llamada al sistema para 'Mostrar Int'
syscall # Ejecutar la llamada al sistema
addi $s2, $s2, 1 # k += 1
j FOR_K # Volvemos al bucle FOR_K
END_FOR_K:
# Imprimir un salto de línea
la $a0, msg_saltoDeLinea # Cargamos la cadena de texto que vamos a mostrar
li $v0, 4 # Cargar en $v0 la llamada al sistema para 'Mostrar String'
syscall # Ejecutar la llamada al sistema
addi $s0, $s0, 1 # i += 1
j FOR_I # Volvemos al bucle FOR_I
END_FOR_I:
# Cargamos de pila los valores de i, j, k, num
lw $s0, 0($sp)
lw $s1, 4($sp)
lw $s2, 8($sp)
lw $s3, 12($sp)
addi $sp, $sp, 16
EXIT: # Salir del programa
li $v0, 10 # Cargar en $v0 la llamada al sistema para 'Salir'
syscall # Ejecutar la llamada al sistema
END_EXIT:
END_MAIN:
# Función que obtiene los dígitos del triángulo de Pascal
TRIANGULO_PASCAL:
IF: # ((i == 0) || (k == 0) || (i == k)) ? GOTO ELSE : CONTINUE
beq $a0, 0, MULTIPLE_CONDITION_OK # (i == 0) ? GOTO MULTIPLE_CONDITION_OK : CONTINUE
beq $a1, 0, MULTIPLE_CONDITION_OK # (k == 0) ? GOTO MULTIPLE_CONDITION_OK : CONTINUE
bne $a0, $a1, ELSE # (i != k) ? GOTO ELSE : CONTINUE
MULTIPLE_CONDITION_OK:
li $v0, 1 # return 1
jr $ra
ELSE:
############################################
##### HERE I TRY DO RECURSIVE FUNCTION #####
############################################
move $t0, $a0
move $t1, $a1
addi $a0, $t0, -1 # i-1
addi $a1, $t1, 0 # k
j TRIANGULO_PASCAL
move $t5, $v0
addi $a0, $t0, -1 # i-1
addi $a1, $t1, -1 # k-1
j TRIANGULO_PASCAL
move $t6, $v0
add $t7, $t5, $t6
move $t7, $v0 # return $t7
jr $ra # Volvemos a la línea después de la llamada
END_IF_ELSE:
END_TRIANGULO_PASCAL:
知道我該如何解決嗎? 我已經搜索信息很長時間了,但無法解決。
謝謝。
PD:兩種代碼均為MCVE,因此將復制粘貼運行。
正如@Jester所建議的那樣,我已更改了C遞歸返回語句,例如:
int trianguloPascal(int i, int k) { if ((i == 0) || (k == 0) || (i == k)) { return 1; } else { /////////////////////////////////// // THIS IS THE CONFLCTING RETURN // /////////////////////////////////// int tmp = 0; tmp = trianguloPascal(i-1, k-1); tmp += trianguloPascal(i-1, k); return (tmp); } }
並且更新的TrianglePascalFunction MIPS代碼為:
TRIANGULO_PASCAL: IF: # ((i == 0) || (k == 0) || (i == k)) ? GOTO ELSE : CONTINUE beq $a0, 0, MULTIPLE_CONDITION_OK # (i == 0) ? GOTO MULTIPLE_CONDITION_OK : CONTINUE beq $a1, 0, MULTIPLE_CONDITION_OK # (k == 0) ? GOTO MULTIPLE_CONDITION_OK : CONTINUE bne $a0, $a1, ELSE # (i != k) ? GOTO ELSE : CONTINUE MULTIPLE_CONDITION_OK: li $v0, 1 # return 1 jr $ra ELSE: li $t8, 0 # int tmp = 0 move $t0, $a0 # $t0 = i move $t1, $a1 # $t1 = k addi $a0, $t0, -1 # i-1 addi $a1, $t1, -1 # k-1 j TRIANGULO_PASCAL add $t8, $t8, $v0 addi $a0, $t0, -1 # i-1 addi $a1, $t1, 0 # k j TRIANGULO_PASCAL add $t8, $t8, $v0 move $v0, $t8 # return $t8 jr $ra # Volvemos a la línea después de la llamada END_IF_ELSE: END_TRIANGULO_PASCAL:
通過此代碼獲得的結果是:
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
因此,我在ELSE語句中出現錯誤,該錯誤始終返回1。為什么會這樣? 任何想法?
最終,我實現了MIPS代碼能夠正常工作。 我將展示如何做到這一點:
.data
var_i: .word 0
var_j: .word 0
var_k: .word 0
var_num: .space 4
msg_pedirNumeroFilas: .asciiz "Input number of rows: "
msg_espacioCorto: .asciiz " "
msg_espacioLargo: .asciiz " "
msg_saltoDeLinea: .asciiz "\n"
.text
# Función principal del programa
MAIN:
# Show message "InputNumRows"
la $a0, msg_pedirNumeroFilas
li $v0, 4
syscall
# Get number of rows
li $v0, 5
syscall
# Save in memory this number of rows
sw $v0, var_num
# Store in saved var our program variables
lw $s0, var_i # Save in $s0 var_i
lw $s1, var_j # Save in $s1 var_j
lw $s2, var_k # Save in $s2 var_k
lw $s3, var_num # Save in $s2 var_num
# Save in stack i, j, k, num
addi $sp, $sp, -16
sw $s0, 0($sp)
sw $s1, 4($sp)
sw $s2, 8($sp)
sw $s3, 12($sp)
# for (i = 0; i < num; i++)
li $s0, 0 # i = 0
FOR_I:
bge $s0, $s3, END_FOR_I # (i >= num) ? GOTO END_FOR_I : CONTINUE
# for (j = num; j > i; j--) {
move $s1, $s3 # j = num
FOR_J:
ble $s1, $s0, END_FOR_J # (j <= i) ? GOTO END_FOR_J : CONTINUE
# Print spaces
la $a0, msg_espacioCorto
li $v0, 4
syscall
addi $s1, $s1, -1 # j -= 1
j FOR_J # GOTO FOR_J
END_FOR_J:
# for (k = 0; k <= i; k++) {
li $s2, 0 # k = 0
FOR_K:
bgt $s2, $s0, END_FOR_K # (k > i) ? GOTO END_FOR_K : CONTINUE
# Print spaces
la $a0, msg_espacioLargo
li $v0, 4
syscall
# Llamada a la función recursiva
move $a0, $s0 # Pass as first argument i
move $a1, $s2 # Pass as second argument k
jal TRIANGULO_PASCAL # Call to triangulo_pascal(i, k)
# Print returned result
move $a0, $v0
li $v0, 1
syscall
addi $s2, $s2, 1 # k += 1
j FOR_K # GOTO FOR_K
END_FOR_K:
# Print \n
la $a0, msg_saltoDeLinea
li $v0, 4
syscall
addi $s0, $s0, 1 # i += 1
j FOR_I # GOTO FOR_I
END_FOR_I:
# Load from stack i, j, k, num
lw $s0, 0($sp)
lw $s1, 4($sp)
lw $s2, 8($sp)
lw $s3, 12($sp)
addi $sp, $sp, 16
EXIT: # Exit program
li $v0, 10
syscall
END_EXIT:
END_MAIN:
# Pascal triangle function
TRIANGULO_PASCAL:
# Save in stack
addi $sp, $sp, -20
sw $ra, 0($sp) # Save StackPointer
sw $s0, 4($sp) # Save i
sw $s1, 8($sp) # Save j
sw $s2, 12($sp) # Save returned value of trianguloPascal(i-1, k-1)
sw $s3, 16($sp) # ave returned value of trianguloPascal(i-1, k)
move $s0, $a0 # $s0 = i actual ((i-1), ((i-1)-1), ...)
move $s1, $a1 # $s1 = k actual ((k-1), ((k-1)-1), k, ...)
IF: # ((i == 0) || (k == 0) || (i == k)) ? GOTO ELSE : CONTINUE
beq $s0, 0, RETURN_1 # (i == 0) ? GOTO RETURN_1 : CONTINUE
beq $s1, 0, RETURN_1 # (k == 0) ? GOTO RETURN_1 : CONTINUE
bne $s0, $s1, ELSE # (i != k) ? GOTO ELSE : CONTINUE
RETURN_1:
li $v0, 1 # return (1)
j END_TRIANGULO_PASCAL # GOTO END_TRIANGULO_PASCAL
END_RETURN_1:
ELSE:
addi $a0, $s0, -1 # i-1
addi $a1, $s1, -1 # k-1
jal TRIANGULO_PASCAL # Call to trianguloPascal(i-1, k-1)
add $s2, $zero, $v0 # $s2 = trianguloPascal(i-1, k-1)
addi $a0, $s0, -1 # i-1
addi $a1, $s1, 0 # k
jal TRIANGULO_PASCAL # Call to trianguloPascal(i-1, k)
add $s3, $zero, $v0 # $s3 = trianguloPascal(i-1, k)
add $v0, $s2, $s3 # return (trianguloPascal(i-1, k-1) + trianguloPascal(i-1, k))
END_IF_ELSE:
END_TRIANGULO_PASCAL:
# Load from stack
lw $ra, 0($sp)
lw $s0, 4($sp)
lw $s1, 8($sp)
lw $s2, 12($sp)
lw $s3, 16($sp)
addi $sp, $sp, 20
jr $ra # Return to $ra
我希望它對與我有同樣問題的其他人有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.