hochsprachecode nach mips

nik_

Vice Admiral
Dabei seit
Sep. 2011
Beiträge
6.239
hi,

folgende prozedur sei gegeben in einer hochsprache:

Code:
public Object calc(int x, int y)
{
 if(y==0)
    return 0;
 else
    return calc(x, y-1)+x;
}
das ganze soll nun in mips (assemlber implementiert werden)

Code:
jal calc
...

calc:
addi $sp, $sp, -4
sw $ra, 0($sp)
bne $a1, $zero, else
addi $v0, $zero, 0
addi $sp, $sp, 4
jr $ra

else:
addi $a1, $zero, -1
jal calc
addi $v1, $v1, $a0
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
das wäre mein code, nur funktioniert er nicht so wie die methode oben.

kann mir da einer von euch helfen?
 

lynxx

Lt. Junior Grade
Dabei seit
Feb. 2005
Beiträge
384
Imho ist der Part falsch:
Code:
    else:
    addi $a1, $zero, -1
    jal calc
    addi $v1, $v1, $a0
...
das soll ja "return calc(x, y-1)+x;" sein, aber momentan ist es eher "calc(-1)" und warum ein zweites Returnregister?
Probier mal:
Code:
    else:
    addi $a1, $a1, -1
    jal calc
    addi $v0, $v0, $a0
...
 

nullPtr

Lt. Junior Grade
Dabei seit
März 2011
Beiträge
348
Noch ein paar Anmerkungen:
1. Der MIPS-Befehlssatz sieht auch Multiplikationen vor ;)
2. Nach einem branch ist im Normalfall immer ein nop zu setzen (branch-deay-slot), insbesondere hier!
 

nik_

Vice Admiral
Ersteller dieses Themas
Dabei seit
Sep. 2011
Beiträge
6.239
es geht nicht darum ob es das gibt. sondern darum, es rekursiv zu implementieren. ist vor allem sinnvoll, wenn keine pseudobefehle benutzt werden sollen.
 

lynxx

Lt. Junior Grade
Dabei seit
Feb. 2005
Beiträge
384
Noch ein paar Anmerkungen:
1. Der MIPS-Befehlssatz sieht auch Multiplikationen vor ;)
Hehe, das dachte ich auch schon, aber dann dachte ich mir das es doch sowieso nur ein Beispiel ist. :D

2. Nach einem branch ist im Normalfall immer ein nop zu setzen (branch-deay-slot), insbesondere hier!
Jein .. der Befehl der direkt einem bedingten Verzweigungsbefehl folgt wird unabhängig davon ob die Verzweigung genommen wurde oder nicht, immer ausgeführt. Es muss nicht zwingend ein nop sein, es erhöht natürlich deutlich die lesbarkeit wenn man das so handhabt.

BTW: MIPS-X hat sogar einen double branch delay slot, führt also die folgenden 2 Befehle in jedem Fall aus.
 

nullPtr

Lt. Junior Grade
Dabei seit
März 2011
Beiträge
348
Klar muss es nicht immer ein nop sein, bei dieser Befehlskonstellation muss es jedoch zwingend eines sein, denn sonst wird $v0 im branch-delay-slot mit 0 überschrieben.
 

nik_

Vice Admiral
Ersteller dieses Themas
Dabei seit
Sep. 2011
Beiträge
6.239
kurz ne frage. muss ich mein $v0 nicht auf dem stack speichern, und zwar vor dem bne. wenn es nämlich nach dem bne da reinhüpft, ist es ja überschrieben. aber in $v0 soll ja das ergebnis von z.b. 2x5 stehen.
 

lynxx

Lt. Junior Grade
Dabei seit
Feb. 2005
Beiträge
384
kurz ne frage. muss ich mein $v0 nicht auf dem stack speichern, und zwar vor dem bne. wenn es nämlich nach dem bne da reinhüpft, ist es ja überschrieben. aber in $v0 soll ja das ergebnis von z.b. 2x5 stehen.
Nein, auf den Stack ist unnötig, da ja die nur die tiefste Rekursion da 0 reinschreibt, allerdings müssen wegen dem branch delay slot einige nop rein damit das wie geplant funktioniert, etwa so:
Code:
.text
main:
addi $a0, $zero, 5
addi $a1, $zero, 2
jal calc
nop
#$v0 ist jetzt 10 (5*2)

addi $v0, $zero, 10 #exit
syscall
nop

calc:
addi $sp, $sp, -4
sw $ra, 0($sp)
bne $a1, $zero, else
nop

addi $v0, $zero, 0
addi $sp, $sp, 4
jr $ra
nop

else:
addi $a1, $a1, -1
jal calc
nop

add $v0, $v0, $a0
lw $ra, 0($sp)
addi $sp, $sp, 4
jr $ra
nop
getestet in MARS (MIPS Assembler and Runtime Simulator) mit aktiviertem delayed branching ("Settings"->"Delayed branching").

BTW: Bei MARS hat man sich dazu entschieden die Option standardmässig zu deaktivieren und auch keine Pseudo-Opcodes oder automatische nop einzufügen da sich Beschwerden häuften das Beispielcodes nicht 1:1 übersetzt wurden.

P.S: Ich persönlich finde diese vielen nop's furchtbar und würde nie so programmieren. :D
 
Zuletzt bearbeitet:
Top