geschrieben am 10.10.2014 12:04:35
Zitat von RPG Hacker: Ich verstehe zwar nicht so viel von N64 Assembler, aber du hast dir auf jeden Fall schonmal meinen Respekt verdient, dass du es überhaupt so weit gebracht und eine erste Version veröffentlicht hast!
Ich hoffe mal, es finden sich Leute, die das Ding nutzen können und davon profitieren.
Danke. Also an sich ist es nicht schwer, Adressierungen sind nur halt anders und man hat sowas wie direct addressing, absolute oder long addressing nicht. Stattdessen ist das dann Register+Base Pointern.
Wenn ich also 'ne Adresse laden will muss ich einfach schreiben:
LUI T1,
$8033 ; Oberer Teil der Adresse T1 := $80330000.[/color]
ORI T1,
R0,
$3D54 ; Unterer Teil der Adresse, T1 := $80333D54
LUI heißt einfach: "Load upper immediate", und "upper" bedeutet ja auch, dass hier die obere Adressenhälfte (die ersten vier bytes von links) angesprochen wird.
ORI ist, wie man erahnen kann, einfach nur OR. Man benutzt es aber hier, da es die bytes nach hinten (also die letzten vier bytes) shiftet und dann kriegt man auch die Adresse raus.
T1 ist ein Register bzw. das "temporary register 1" das für temporäre Werte verwendet wird. R0 ist auch ein Register, ist aber immer null. Man verwendet es sicherheitshalber um Fehler zu vermeiden, kann nämlich passieren, das wenn man gleiche Register ORI'd, dass dann irgendein Fehler entsteht und der Wert nicht mehr stimmt. Deshalb benutzt man immer R0.
Will ich jetzt einen Wert von einer Adresse, mache ich das gleiche mit LUI nochmal, nur das ich danach nicht ORI benutze sondern den Befehl LW, LB oder LH. (LW = Load Word (ladet 'nen 32-bit wert), LB = Load Byte (ladet 'nen 8-bit wert) oder LH = Load Halfword (Ladet 'nen 16-bit wert))
LUI T1,
$8033 ; Obere Adressenhälfte. T1 := $80330000
LB T2,
$3D54(
T1)
; Lade Wert von Adresse $80333D54 in T2. T1 bleibt UNVERÄNDERT -> T1 ist immernoch: $80330000.
In dem Falle wird jetzt ein Byte-Wert von $80333D54 in T2 geladen. Wenn also bei $80333D54 steht: 0D 02 00 A2 D1 [...] wird nur das "0D" genommen und lädt es in T2. -> T2 := $0000000D. Bei Halfword hätte er jetzt $0D02 und bei 'nem Word hätte er $0D0200A2 geladen. Ich glaube aber, dass hier irgendwas noch mit Big-Endian und Little-Endian war, so das das bei manchen ROMs auch umgekehrt geshiftet wird. Kann also auch sein, dass $0D0200A2 vertauscht sind und man dann $A200020D hat. Mario 64 ist auf jedenfall Little-Endian.
Kannst auch einen Wert speichern, dafür gibts dann SW, SH, SB. Also Store word, Store Halfword oder Store Byte. Prozess ist der Gleiche. SB hat dabei 'nen Register wo der Wert reingeladen wird und die Adresse verknüpft mit dem Register, dass die obere Adressenhälfte in sich trägt:
LUI T0,
$8033 ; Obere Adressenhälfte. T0 := $80330000
ORI T1,
R0,
$000A ; Unser Byte: $0A -> Wert.
SB T1,
$3D54(
T0)
; Speichert den Wert (LSB -> Least Significant Byte, $0A) aus T1 an Adresse $80333D54. T0 bleibt wieder unverändert und ist immernoch $80330000
Hier wird das Register "T1" als der zu speichernde Wert verwendet und wieder Pointer+Base Syntax zur Adresse und anschließend wird das Byte dort gespeichert. Nach diesem Code würde statt
0D 02 00 A2 D1 jetzt
0A 02 00 A2 D1 stehen.