MIPS中的递归 - Pascal三角形

时间:2018-03-24 00:44:52

标签: assembly mips

我正在做一个Pascal Triangle来练习MIPS,但是当我必须做递归函数时,我的代码会中断。我不知道要做代码中标记的return语句:

首先,我将展示我正在翻译的C代码,最后,您可以看到冲突的退货声明(已标记)

// 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代码,最后,您可以看到冲突的地方,我尝试执行此冲突的返回语句(已标记)

// 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,因此将运行复制粘贴。


<小时/> 编辑1:

正如@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.为什么会这样?任何的想法?

1 个答案:

答案 0 :(得分:0)

最后,我实现了MIPS代码的工作原理。我将展示我是如何做到的:

        Ext.create('Ext.form.field.ComboBox', {
           renderTo: Ext.getBody(),
           fieldLabel: 'Select an option',
           store: Ext.create('Ext.data.Store', {
               fields: ['optionName', 'value'],
               data: [
                    {
                        value: 1,
                        optionName: 'First Option'
                    },
                    {
                        value: 2,
                        optionName: 'Second Option'
                    },
                    {
                        value: 3,
                        optionName: 'Third Option'
                    }
                ]
           }),
           emptyText: 'Select...',
           displayField: 'optionName',
           valueField: 'value'
        });

我希望它对那些和我有同样问题的人有用。