Die Assemblersprache des Sparc ist sehr einfach aufgebaut. Sie besteht grundsätzlich nur aus symbolischen Konstanten, Kommentaren, Codierungsdefinitionen, Labels ,den Mnemonics und den Werten, die eingesetzt werden sollen.
Konstanten:
Konstante werden, wie es sich gehört, vor der Assemblierung vollständig durch ihren zugehörigen Wert ersetzt. Konstanten können dabei stehen, wo sie wollen. Sie werden durch folgende Befehlszeile definiert:
Konstantenname=Wert
So kann man beispielsweise zur besseren †bersichtlichkeit das Register %l0 per
Laufvariable=l0
umbenennen. Jeder Zugriff auf %Laufvariable greift jetzt automatisch auf %l0 zu.
Kommentare:
Kommentare sind in Assembler etwas vom Wichtigsten, das es gibt. Normalerweise besteht der Kommentartext aus mehr Zeichen, wie der Code selbst. Denn Assemblercode ist so unübersichtlich und verwirrend, dass jeder Kommentar eine Hilfe für später sein kann. Kommentare können immer am Ende einer Zeile mit einem Ausrufezeichen vornedran stehen:
! Kommentaräää.
Codierungsdefinitionen:
Unter Codierungsdefinitionen versteht man das Festlegen der Art des Assemblats, das aus dem Text entstehen soll. Es sind die folgenden:
.data !Nach dieser Definition folgen die (statischen) Variablen .text !Nach dieser Definition folgt der in Maschinenbefehle zu übersetzende Text. .bss !Nach dieser Definition folgt der Stack .skip n !Lasse n Bytes freien Speicherplatz .align n !Aligniert alle nachfolgenden Definitionen an die zusätzlich angegebene Anzahl n Bytes .global !Global-Definition, angegeben werden müssen Name und Grösse .common !Wird für FORTRAN benutzt .empty !Wird für Delay-Slot benutzt Ab hier stehen Variablendefinitionen. Sie werden von einem oder mehreren, durch Kommata getrennten Namen gefolgt. .ascii !Asciizeichen ohne abschliessendes Nullbyte .asciz !Asciizeichen, Damit können Strings festgelegt werden. .byte !8-Bit-Variable .half !16-Bit-Variable .word !4 Bytes = integer-Variable .single !4 Bytes-floating-point .double !8 Bytes-floating-point .quad !16-Bytes-floating-point
Labels:
Labels sind Namen mit einem Doppelpunkt, die eine Adresse representieren. Sie können irgendwo am Anfang einer Zeile stehen. Der Assembler wird sich diese Adressen merken und bei Sprüngen (Branches), genau diese einsetzen. Beispiel:
Schleife: !Ein Label mit dem Namen Schleife
ba Schleife !Springe zum Label Schleife
nop !Dieses Programm ist die Definition einer Endlosschleife.
Mnemonics:
Mnemonics sind kleine Abkürzel für die entsprechenden Maschinenbefehle. Beispiele dafür sind ADD, MULCC, MOV, ä
Werte:
Als Werte kommen in Frage: Dezimalzahlen, Hexadezimalzahlen, Zeichen, Strings, Adressen, Register, Adressregister, Labels (Dies sind eigentlich auch nur Adressen), Variablen (ebenfalls nur Adressen)
Die Werte werden immer in der gleichen Reihenfolge aufgeschrieben:
[[Quelle1, [Quelle2,]] Ziel]
Ein Befehl wie nop braucht überhaupt keine Werte.
Befehle wie Branches brauchen nur ein Ziel: Das Label.
Befehle wie ST oder LD brauchen nur eine Quelle und ein Ziel.
Befehle wie AND brauchen zwei Quellen und ein Ziel.
Hier werden Register immer mit reg abgekürzt, Werte immer mit val, Konstante Werte bis xx Bits mit constxx. Die wichtigsten Befehle des Sparc sind nun die folgenden, wobei synthetische Befehle ein * vornedran haben.
Speicher- und Registerbefehle: rdy %y, reg !liest das Y-Register aus wry reg1, reg2, %y !schreibt den den Wert reg1 XOR reg2 ins Y-Register wry reg1, const13, %y !schreibt den den Wert reg1 XOR const13 ins Y-Register ldub [reg1, reg2], reg !lädt ein unsigned byte an Speicherstelle reg 1+2 ldub [reg1, const13],reg !lädt ein unsigned byte an Speicherstelle reg1+const13 ldsb [reg1, reg2], reg !lädt ein signed byte an Speicherstelle reg 1+2 ldsb [reg1, const13],reg !lädt ein signed byte an Speicherstelle reg1+const13 lduh [reg1, reg2], reg !lädt ein unsigned 2-byte an Speicherstelle reg 1+2 lduh [reg1, const13],reg !lädt ein unsigned 2-byte an Speicherstelle reg1+const13 ldsh [reg1, reg2], reg !lädt ein signed 2-byte an Speicherstelle reg 1+2 ldsh [reg1, const13],reg !lädt ein signed 2-byte an Speicherstelle reg1+const13 ld [reg1, reg2], reg !lädt ein 4-byte an Speicherstelle reg 1+2 ld [reg1, const13],reg !lädt ein 4-byte an Speicherstelle reg1+const13 ldd [reg1, reg2], reg !lädt ein 8-byte an Speicherstelle reg 1+2 ldd [reg1, const13],reg !lädt ein 8-byte an Speicherstelle reg1+const13 stb reg, [reg1, reg2] !speichert unteres byte an Speicherstelle reg 1+2 stb reg, [reg1, const13] !speichert unteres byte an Speicherstelle reg1+const13 sth reg, [reg1, reg2] !speichert unteres 2-byte an Speicherstelle reg 1+2 sth reg, [reg1, const13] !speichert unteres 2-byte an Speicherstelle reg1+const13 st reg, [reg1, reg2] !speichert reg an Speicherstelle reg 1+2 st reg, [reg1, const13] !speichert reg an Speicherstelle reg1+const13 std reg, [reg1, reg2] !speichert reg und reg+1 an Speicherstelle reg 1+2 std reg, [reg1, const13] !speichert reg und reg+1 an Speicherstelle reg1+const13 swap [reg1, reg2], reg !Vertauscht reg mit Speicherstelle reg 1+2 swap [reg1, const13],reg !Vertauscht reg mit Speicherstelle reg1+const13 *set val, reg !Schreibt den beliebigen val in reg *clr reg !setze reg auf 0 *clr Adresse !setze 4*Byte an Adresse auf 0 *clrh Adresse !setze 2*Byte an Adresse auf 0 *clrb Adresse !setze Byte an Adresse auf 0 *mov reg1/val1, reg !kopiere reg1/val1 in reg, reg und reg1 kann auch %y sein Mathematische Operatoren: *neg reg !Zweierkomplement reg=-reg add(cc) reg1, reg2, reg !Addiert reg 1 und 2 add(cc) reg1, const13, reg !Addiert reg1 und const13 sub(cc) reg1, reg2, reg !Subtrahiert reg 2 von 1 sub(cc) reg1, const13, reg !Subtrahiert const13 von reg1 *inc(cc) reg !Addition von 1 *inc(cc) const13, reg !Addition von const13 *dec(cc) reg !Subtraktion mit 1 *dec(cc) const13, reg !Subtraktion mit const13 Logische Operatoren: In Klammern das Resultat der Verknüpfung von (0011) mit (0101) *not reg !Einerkomplement (Bits umkehren) or(cc) reg1, reg2, reg !OR-Verknüpfung von reg 1 und 2 (0111) or(cc) reg1, const13, reg !OR-Verknüpfung von reg1 und const13 (0111) orn(cc) reg1, reg2, reg !Verknüpfung von reg 1 OR NOT 2 (1011) orn(cc) reg1, const13, reg !Verknüpfung von reg1 OR NOT const13 (1011) and(cc) reg1, reg2, reg !AND-Verknüpfung von reg 1 und 2 (0001) and(cc) reg1, const13, reg !AND-Verknüpfung von reg1 und const13 (0001) andn(cc) reg1, reg2, reg !Verknüpfung von reg 1 AND NOT 2 (0010) andn(cc) reg1, const13, reg !Verknüpfung von reg1 AND NOT const13 (0010) xor(cc) reg1, reg2, reg !XOR-Verknüpfung von reg 1 und 2 (0110) xor(cc) reg1, const13, reg !XOR-Verknüpfung von reg1 und const13 (0110) xnor(cc) reg1, reg2, reg !Verknüpfung von reg 1 XOR NOT 2 (1001) xnor(cc) reg1, const13, reg !Verknüpfung von reg1 XOR NOT const13 (1001) sll reg1, reg2, reg !logische Linksverschiebung (mit 0 auffüllen) srl reg1, reg2, reg !logische Rechtsverschiebung (mit 0 auffüllen) sra reg1, reg2, reg !arithmetische Rechtsverschiebung (miteinbezug vom Sign) *btst reg1, reg2 !Bittest: ist reg1 in reg2? *btst const13, reg2 !Bittest: ist const13 in reg2? *bset reg1, reg2 !Setze Bit reg1 in reg2 *bset const13, reg2 !Setze Bit const13 in reg2 *bclr reg1, reg2 !Lösche Bit reg1 in reg2 *bclr const13, reg2 !Lösche Bit const13 in reg2 *btog reg1, reg2 !Vertausche Bit reg1 in reg2 *btog const13, reg2 !Vertausche Bit const13 in reg2 Sprungbefehle: Für die Trap-Befehle gelten die gleichen Abkürzungen, nur mit einem t anstelle des b. *cmp reg1, reg2 !Vergleiche reg 1 und 2 *cmp reg1, const13 !Vergleiche reg1 und const13 *tst reg !logischer Test von reg ba Label !Verzweige immer bn Label !Verzweige nie be Label !Verzweige, wenn gleich bne Label !Verzweige, wenn ungleich bl Label !Verzweige, wenn kleiner ble Label !Verzweige, wenn kleinergleich bg Label !Verzweige, wenn grösser bge Label !Verzweige, wenn grössergleich blu Label !Verzweige, wenn kleiner (ohne Vorzeichen) bleu Label !Verzweige, wenn kleinergleich (ohne Vorzeichen) bgu Label !Verzweige, wenn grösser (ohne Vorzeichen) bgeu Label !Verzweige, wenn grössergleich (ohne Vorzeichen) bpos Label !Verzweige, wenn positiv bneg Label !Verzweige, wenn negativ bcs Label !Verzweige, wenn Carry=1 bcc Label !Verzweige, wenn Carry=0 bvs Label !Verzweige, wenn Overflow=1 bvc Label !Verzweige, wenn Overflow=0 *call Label !Funktionsaufruf zu Adresse Label *call reg !Funktionsaufruf zu Adresse in reg *jmp Label !Sprung in eine Sub jumpl Label, reg !Leaf-Sprung mit Speicherung des IP in reg rett Label !Wiederherstellung nach einem Trap *ret !Rücksprung aus einer Sub *retl !Rücksprung aus einer Leaf-Sub Sonstige Befehle: nop !Zigarettenpause sethi const22, reg !setzen der höchsten 20 Bits des reg save !Register-Window speichern und wechseln save reg1, reg2, reg !gleich wie save und reg = reg 1+2 save reg1, const13, reg !gleich wie save und reg = reg1+const13 restore !Register-Window wiederherstellen und wechseln restore reg1, reg2, reg !gleich wie restore und reg = reg 1+2 restore reg1, const13, reg !gleich wie restore und reg = reg1+const13 Des weiteren gibt es noch einige floating-point-Befehle; mathematische Befehle und Sprungbefehle. Sie sind momentan noch nicht vorhanden.Hier die Belegung der Register:
%r0 = %g0 = Abfall-Register und Wert Null
%r1 = %g1 -
%r2 = %g2 -
%r3 = %g3 -
%r4 = %g4 -
%r5 = %g5 - reserviert
%r6 = %g6 - reserviert
%r7 = %g7 - reserviert
%r8 = %o0 \
%r9 = %o1 \
%r10 = %o2 \ o0 bis o5:
%r11 = %o3 / frei verfügbar und bentigt für Parameterübergabe
%r12 = %o4 /
%r13 = %o5 /
%r14 = %o6 =%sp Stackpointer
%r15 = %o7 =%pc, wenn Funktionsaufruf
%r16 = %l0 -
%r17 = %l1 -
%r18 = %l2 - Die lokalen Register stehen innerhalb einer
%r19 = %l3 - Funktion gänzlich zur Verfügung. Sie sollten
%r20 = %l4 - am besten als einzige verwendet werden,
%r21 = %l5 - um Fehler zu vermeiden.
%r22 = %l6 -
%r23 = %l7 -
%r24 = %i0 \
%r25 = %i1 \
%r26 = %i2 \ i0 bis i5:
%r27 = %i3 / Übergebene Parameter
%r28 = %i4 /
%r29 = %i5 /
%r30 = %i6 =%fp Framepointer
%r31 = %i7 =%ret alter %pc (dort, wo der Befehl CALL steht)
%y Y-Register (Multiplikation und Division)
%pc Program-Counter (Befehlszeiger) (Nur über Jumps und Branches veränderbar)
%npc next-Program-Counter
%psr Prozessor-Status-Register (Nur im Supervisor-Mode Zugriff)
%wim Window-Invalid-Mask-Register (Nur im Supervisor-Mode Zugriff)
%tbr Trap-Base-Register (Nur im Supervisor-Mode Zugriff)
%fsr Float-Point-Status-Register (Koprozessor-Status)
%psr: F E D C B A 9 8 7 6 5 4 3 2 1 0 F E D C B A 9 8 7 6 5 4 3 2 1 0
--------+-----------------------+----------+------------------+--+--+----------+--+--+--+---------------+
| CPUID | ICC | 0 0 0 0 0 0 |EC|EF| PIL | S|PS|ET| CWP |
--------+-----------------------+----------+------------------+--+--+----------+--+--+--+---------------+
CPUID : Typ und Version des Prozessors (ist fest eingelötet)
ICC : Condition-Code-Flags (Carry-, Overflow-, Sign- und Zero-Flag)
EC : Enable Coprocessor (ist 1, wenn ein Koprozessor vorhanden ist)
EF : Enable Floatpoint
PIL : Processor-Interrupt-Level (Nur Interrupts mit höherer IRL werden abgearbeitet)
S : Supervisor-Mode-Flag (Ist 1, wenn der Prozessor im Supervisor-Mode arbeitet)
PS : Previous-Supervisor-Mode-Flag (speichert das S-Flag während eines Traps)
ET : Enable Trap: (Ist 1, wenn Traps erlaubt sind)
CWP : Current Window Pointer (enthält die Nummer des aktiven Register-Windows)
%tbr: F E D C B A 9 8 7 6 5 4 3 2 1 0 F E D C B A 9 8 7 6 5 4 3 2 1 0
--------+----------------------------------------------------------+-----------------------+------------+
| TBA | TT | 0 0 0 0 |
--------+----------------------------------------------------------+-----------------------+------------+
TBA : Trap Base address, enthält die Adresse der Trap-Handler-Vektor-Tabelle
TT : Trap Type, enthält die Nummer des Traps (256 möglich)
Das %tbr gibt somit stets die absolute Adresse des Anspringpunktes für den Handler-Vektor an.
%fsr: F E D C B A 9 8 7 6 5 4 3 2 1 0 F E D C B A 9 8 7 6 5 4 3 2 1 0
--------+-----+-----+-------------+------------------+-------+------+----+---------------+--------------+
| RD | | TEM | | FTT | | FCC| | CEXC |
--------+-----+-----+-------------+------------------+-------+------+----+---------------+--------------+
RD : Rundungs-Modus: 0=nächste Zahl, 1=gegen 0, 2=+unendlich, 3=-unendlich
TEM : Trap-Enable-Mask, aktiviert und deaktiviert verschiedene Traps
FTT : Floatpoint-Trap-Type: Gibt die Trapnummer an
FCC : Condition Codes des Koprozessors
CEXC : Current Exception-Field, gibt an, welche Ausnahmen nach einer Operation auftraten.