Okay, hier ist die ASM. Es ist Prädikat auf den Pseudo-Code oben, aber ich schrieb es von Grund auf neu, basierend auf dem HLL an der Spitze.
Es ist Mips ABI konform. Somit ist es möglich, die Argumentregister zu ändern (d. H. Zu zerstören). Wenn der Anrufer in einer Schleife angerufen wird, muss er daher vor jedem Anruf a0-a3
setzen.
# void
# swap(int v[],int k,int j)
# {
# int temp;
#
# temp = v[k];
# v[k] = v[j];
# v[j] = temp;
# }
# swap -- swap two elements in an array
#
# arguments:
# a0 -- pointer to array
# a1 -- array index "k"
# a2 -- array index "j"
#
# registers:
# t0 -- v[k]
# t1 -- v[j]
swap:
sll $a1,$a1,2 # k <<= 2 (i.e. byte offset)
addu $a1,$a1,$a0 # get address of v[k]
sll $a2,$a2,2 # j <<= 2 (i.e. byte offset)
addu $a2,$a2,$a0 # get address of v[j]
lw $t0,0($a1) # fetch v[k]
lw $t1,0($a2) # fetch v[j]
sw $t1,0($a1) # v[k] = v[j]
sw $t0,0($a0) # v[j] = v[k]
jr $ra # return
UPDATE:
Ich weiß sll
steht für Verschiebung links. Was bedeutet addu
?
Die u
"Suffix" steht für unsigned. Aber, nicht wie es in vielen anderen Orten verwendet wird.
Es gibt zwei Versionen [von add
]. Die signierte Version ist add
und die unsignierte Version addu
. Sie beide produzieren genau die gleichen Ergebnisse, weil sie beide die gleichen Zweiergänzung ergänzen.
Der nur Unterschied ist, dass, wenn eine Addition einen Überlauf verursacht, add
einen Prozessor Ausnahme erzeugen wird (beispielsweise „arithmetischer Überlauf“), jedoch wird addu
nicht --Es wird einfach einzuwickeln. Ähnlich für sub
und Unterlauf.
Wenn zum Beispiel ein Register 0x7FFFFFFF
enthält und Sie eins hinzufügen, führt dies zu einem Überlauf. Das ist, weil Sie beginnen sind mit dem maximalen positivem Wert unterzeichnet, Sie ein, um es hinzuzufügen, und voila Sie auf dem maximalen negativen Wert (dh einen „Quantensprung“, bekannt als Überlauf) unterzeichnet .
Also, wenn Dinge hinzufügen, die legitim Überlauf (d. H. "Wrap" in 32 Bits) wie Adressberechnungen, ist es besser, die unsignierte Version zu verwenden.
Das liegt daran, dass in Mips einige Teile des Programms [code/data/stack] bei 0x80000000 oder höher geladen werden können.
Zum Beispiel kann der Stapel könnte bei 0x80001000
beginnen und wenn Sie genügend Daten auf schieben (das heißt das $sp
Register wird mit sub
verringert), wird es trifft schließlich die Nachbarschaft von 0x80000000
. Wenn Sie in die Nähe dieser Adresse drücken/springen, erhalten Sie einen Überlauf/Unterlauf.
Dies ist nicht falsch - es ist natürlich, und Sie wollen nicht den Prozessor eine Ausnahme zu erzeugen, wenn Sie die sub
für den Push-Betrieb zu tun, so dass Sie verwenden subu
[und/oder die sofort Form der Anweisung subiu
].
Wenn Sie es noch nicht gefunden haben, hier ist eine ziemlich gute Befehlssatzreferenz [die eine Menge Leute verwenden]: http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html Es ist ein einfaches Lesen und deckt die meisten Anweisungen ab, die Sie wahrscheinlich benötigen/verwenden .
Hier ist ein kurzer Überblick über die ABI-Aufrufkonventionen: http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/altReg.html
Denken Sie darüber nach, wie die Compiler implementiert es: sie legt nur eine Reihe von aufeinanderfolgenden Speicherplatz und speichert einen Zeiger auf den ersten. Um eine Adresse zu berechnen, berechnen Sie einfach einen Offset von diesem - z.B. Index 0 ist ein Offset von 0 * 32 (0), Index 1 ist 1 * 32, Index 2 ist 2 * 32 usw. (BTW ist es viel einfacher, von C zu MIPS Assembly Language als von Java zu MIPS Assembly Language gehen) . – EJoshuaS