2012-03-25 15 views
3

Also ich arbeite jetzt seit ein paar Tagen daran, und ich habe es geschafft, alles durchzubekommen, außer ein Teil bringt mich.C to MIPS trouble

int mystery(int a0) 
{ 
    if (a0 == 0) 
    { 
     return 0; 
    } 
    else 
    { 
     return mystery(a0 - 1) + a0; 
    } 
} 

Ich habe diese rekursive Funktion und ich habe einige MIPS-Code. Der C-Code funktioniert, aber ich habe ein Problem irgendwo in meinem MIPS-Code, der in mache es nicht kommt richtig über Putten 2.

.text 

main: 

li $a0, 2 
jal mystery 
move $a0, $v0 
jal putDec 
li $a0, '\n' 
li $v0, 11 
syscall 

li $a0, 3 
jal mystery 
move $a0, $v0 
jal putDec 
li $a0, '\n' 
li $v0, 11 
syscall 

li $v0, 10  
syscall 

putDec: 
    li $v0, 1 
    syscall 
    jr $ra  

mystery: 
bne $0, $a0, recur 
li $v0, 0  
jr $ra    

    recur: 
sub $sp, $sp, 8  
sw $ra, 4($sp) 
sub $a0, $a0, 1 
jal mystery   
sw $v0, 0($sp) 
jal mystery   
lw $t0, 0($sp) 
addu $v0, $v0, $t0 
addu $v0, $v0, 1  
add $a0, $a0, 1  
lw $ra, 4($sp) 
add $sp, $sp, 8  
jr $ra  

Alles bis zu dem Label ‚Geheimnis‘ ist in Ordnung, es gerade dort als a Formalität, um Argumente einzubringen und danach zu drucken. Das Problem, das ich habe, ist Werte über 3 zu bekommen, um die richtigen Zahlen auszudrucken. Hilfe würde sehr geschätzt werden, wenn jemand sehen könnte, wo ich meinen Fehler mache. Danke

+2

Was zurückzukehren passiert, wenn Sie dies lief im Debugger? –

+0

Scheint richtig, dies auf Stapelüberlauf zu posten. NB: Die Ackerman-Funktion wird wahrscheinlich schneller sein. – wildplasser

+0

Wenn ich dies in MARs drucke druckt 3 und 7. – budokiba

Antwort

0

Whoo nach umfangreicher Arbeit und Verfolgung des Codes Schritt für Schritt denke ich, dass ich es endlich geschafft habe, musste aber einiges ändern, aber eigentlich scheint jetzt einfacher. Hier ist der Code für den Fall, dass Sie nochmal darüber schauen wollen, wenn Sie ein Problem sehen, das bei bestimmten Werten auftreten könnte, die ich nicht getestet habe. Danke für die Hilfe alle.

Neue rekursive Geheimnis Funktion:

mystery: 
bne $0, $a0, recur  
li $v0, 0  
jr $ra    

recur: 
    sub $sp, $sp, 8 
    sw $ra, 4($sp)  
    sw $a0, 0($sp) 
    sub $a0, $a0, 1 
    jal mystery  
    lw $t0, 0($sp) # 
    addu $v0, $v0, $t0  
    lw $ra, 4($sp)  
    add $sp, $sp, 8 
    jr $ra   

Nochmals vielen Dank. :)

3

Versuchen Sie einen Schritt zurück und vergleichen Sie die Struktur des C und Assembler-Code, ohne sich zu viele über die Details zu sorgen.

Im C-Code gibt es eine Bedingung, die entweder zu einem Basisfall (der nur einen Wert zurückgibt) oder zum rekursiven Fall führt. Der rekursive Fall führt eine Subtraktion, den rekursiven Aufruf an mystery und eine Addition durch.

Sehen Sie sich nun die Assembly-Version an: auch dies hat eine Bedingung, die entweder zu einem Basisfall oder zu einem rekursiven Fall führt. Aber schau dir die Struktur des rekursiven Falles an: Es gibt zwei rekursive Aufrufe an mystery da! Das ist ein starker Hinweis darauf, dass es unwahrscheinlich ist, dasselbe zu tun ...

+0

+1 Weil Sie etwas zu verstehen scheinen, dass die meisten SO-Schädeln von Brei nicht tun: Beantworten von Fragen wie dieser sollte ein Moment für die Bildung sein, kein Moment, um ein einfaches zu gewinnen Antworten. –

0

Sie nehme an, die ASCII-Symbol, ändern "li $ v0, 1" in putDec auf "li $ v0, 11" (das war kein Fehler)

+0

Ja, das musste ich zuerst tun, aber um das zugrunde liegende Konzept besser zu verstehen, war es einfacher, es als Dezimalzahl zu betrachten. Von dort konnte ich überprüfen, welche ASCII-Zeichen durch diese Nummer repräsentiert werden. Dies erleichterte es, Probleme zu erkennen und im Code auf Korrektheit zu prüfen. Dann musste ich nur den Systemaufrufwert auf 11 zurückstellen, als ich sicher war, dass alles andere korrekt war. – budokiba