2017-10-17 13 views
1

J'essaie de convertir un code C en code MIPS.Appels de fonction imbriqués MIPS

int main() { 
    int a; 
    int b; 
    int result = 0; 
    if (a != b) 
    result = test(a, b); 
    else 
    result = a + b; 
    return result; 
} 
int test(int a, int b) { 
    if (a > b) 
    return multiply(a, b) 
    else 
    return subtract(a, b) 
} 
int multiply(int a, int b) { 
    return a * b; 
} 
int subtract(int a, int b) { 
    return a - b; 
} 

Ce code contient des appels de fonction imbriqués à l'intérieur de la fonction de test. J'ai mis l'adresse de retour de la fonction de test dans la pile et essaye de renvoyer la valeur soustraite ou multipliée à la main.

Mais dans mon cas, mon code exécute à la fois des fonctions de soustraction et de multiplication. J'essaie de mettre mon résultat à s0. Après avoir exécuté s0 montre toujours la soustraction des valeurs. Si je mets multiplier le résultat à s1, s1 montre la vraie valeur.

Je pense que la soustraction de fonction remplace la valeur à s0. Mais quand le cas est multiplié, pourquoi la méthode de soustraction est appelée? J'ai un bloc if/else, mais cette partie ne semble pas fonctionner.

Voici mon code MIPS, qu'est-ce que je fais mal?

.data 
    numberA: .word 4 
    numberB: .word 2 
.text 
.globl main 

    main: 
    addi $s0, $0, 0 # result = 0 
    lw $a0, numberA 
    lw $a1, numberB 

    bne $a0, $a1, L1 
    add $s0, $a0, $a1 
L1: jal test 

    add $s0, $v0, $0 

    li $v0,10 
    syscall 


test: 
     addi $sp, $sp, -4 
     sw $ra, 0($sp) 

     slt $s1,$a1,$a0 
     bne $s1, 1, ELSE 
     jal multiply 
ELSE: jal subtract 

lw $ra, 0($sp) 

addi $sp, $sp, 8 

jr $ra 


subtract: 
    sub $s0, $a0, $a1 
    jr $ra 


multiply: 
    mult $a0, $a1 
    mflo $s0 
    jr $ra 
+0

Ce n'est pas une fonction imbriquée. Ce serait 'int foo() {int imbriqué() {return 1;} blah blah foo(); blah foo(); } ', où' nested() 'peut accéder aux variables locales dans' foo'. GCC soutient cela: https://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html. Ce que vous faites est juste de faire des appels de fonction à partir d'une fonction. C'est normal. Les fonctions qui ne font aucun appel s'appellent des fonctions de feuille (elles sont des feuilles de l'arbre d'appel). Donc, vous demandez vraiment comment écrire des fonctions non-feuille dans MIPS. –

Répondre

2

Le problème est que lorsque vous revenez de se multiplient, vous encore appel Soustraire dans la ligne suivante. Vous devez retourner à partir de la fonction test après avoir appelé multipliez. Cependant, étant donné que les appels de fonction sont à la fois la dernière instruction de votre fonction, vous pouvez utiliser le raccourci suivant:

test: 
     slt $s1,$a1,$a0 
     bne $s1, 1, ELSE 
     j multiply 
ELSE: j subtract 

De cette façon, vous n'avez pas stocker le $ ra dans la pile, mais vous pouvez directement l'utiliser pour accéder à l'appelant de essai dans le jr $ra de soustraction et de multiplication . De cette façon, cela devrait fonctionner comme prévu.

Vous pouvez également sauter sur jal subtract après son retour de se multiplier:

 jal multiply 
     j OUT 
ELSE: jal subtract 

OUT: ... 
+0

Merci pour votre réponse rapide, mais je dois utiliser la pile, parce que c'est mes devoirs :) – mekafe

+1

@ mekafe Ok, alors utilisez la méthode alternative, le point est: ne saute pas en soustrayant après le retour de multiplier – Ctx