Mandalex

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.