2017-08-23 11 views
1

Je suis un débutant en programmation depuis quelques mois et je me suis contenté de bidouiller un code d'assemblage. J'ai rencontré un problème avec mon code MIPS et j'ai réduit le problème à ma boucle après l'impression de la valeur de chaque variable. Il imprime uniquement 1 à la suite d'une entrée entière. Essentiellement, je suis en train de convertir ceci:Convertir du code C en MIPS - Fonction factorielle itérative

int fac(int k) { 
    int i, f = 1; 
    for (i = 1; i <= k; i++) { 
     f = f * i; 
    } 
    return f; 
} 

à ceci:

fac: 
    move $t4, $t0 #$t0 is the input from the user and $t4 is k in the C code 
    li $t1, 1 #$t1 is f in the C code, initialising it to 1 
    li $t2, 1 #$t2 is i in the C code, declaring it as 1 
    loop: 
    ble $t2, $t4, end_loop #i<=k, end the loop 
    mul $t1, $t1, $t2 #f=f*i 
    addi $t2, $t2, 1 
    j loop 
    end_loop: 

Je l'ai testé le code en mettant dans un tas de déclarations d'impression et a été en mesure d'obtenir t4 $ et t0 $, comme input mais à la fois $ t1 et $ t2 restent à 1 après la boucle. Dois-je sauter dans la boucle?

+0

Tout cela pourrait être facilement résolu avec un débogueur, donc je vais juste laisser avec un indice: vous avez trompé le but de la condition de la boucle for dans votre code d'assemblage. Et un conseil général: jetez un oeil aux conventions sur le codage d'assemblage et en particulier sur l'assemblage MIPS. – Paul

Répondre

2
ble $t2, $t4, end_loop #i<=k, end the loop 

Non, la deuxième partie d'une déclaration C for est la condition pour laquelle vous voulez continuer la boucle, pas fin.

Ce que vous faites ici est même pas entrer le corps de la boucle, ce qui explique pourquoi $t1 et $t2 rester la même valeur que vous les initialisés à. Vous souhaitez probablement utiliser bgt plutôt que ble

+0

Ok merci, donc je voudrais quelque chose comme bgt $ t2, $ t4, end_loop? Où si i est plus grand que k il se termine à droite? –

+0

@ChristianPeterson, oui. – paxdiablo

0

Votre condition de boucle avec ble $t2, $t4, end_loop #i<=k, end the loop mettra fin à la boucle si i<=k mais à la place vous voulez l'exécuter tant que cette condition est altérée. Votre mise en œuvre de la boucle ne pénètre même pas la boucle pour les entrées factoriels plus 1.

Edit: Comme dit dans les commentaires avec le code suivant j'ai mis en place une boucle do {...} while(); qui n'est pas ce que l'OP a demandé. Cependant, le code fonctionnerait. Ci-dessous le texte caressé la réponse réelle (for implémentation de la boucle) suit.

Retirez l'étiquette end_loop: et sauter à l'étiquette loop: avec ble en dernier lieu déclaration:

fac: 
    move $t4, $t0 #$t0 is the input from the user and $t4 is k in the C code 
    li $t1, 1 #$t1 is f in the C code, initialising it to 1 
    li $t2, 1 #$t2 is i in the C code, declaring it as 1 
    loop: 
    mul $t1, $t1, $t2 #f=f*i 
    addi $t2, $t2, 1 
    ble $t2, $t4, loop #i<=k, loop goes on if not this doesn't jump 

Pour mettre en œuvre la boucle que vous avez demandé, vous devez changer le ble (<=):

ble $t2, $t4, end_loop #i<=k, end the loop 

à bgt (>):

bgt $t2, $t4, end_loop #i>k, end the loop 
+0

@paxdiablo: Sa réponse a été la première quand j'ai commencé à écrire ceci. –

+0

Merci pour l'aide. Je comprends, essentiellement ma condition est maintenant de continuer la boucle, mais il se termine en fonction de l'étiquette à laquelle il saute. –

+0

C'est subtilement différent de la boucle C 'for'. Votre boucle s'exécutera au moins une fois, il est possible que la variante C s'exécute zéro fois. – paxdiablo