D. Assembler, Compiler, Binder D.1.1 Einordnung und ...€¦ · Assembler: der Begriff wird oft unscharf verwendet, manchmal das Hilfsprogramm zur Assemblierung, manchmal die Assemblersprache.
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
D.1.1 Einordnung und ZielsetzungAssemblersprache als mnemonische Notation für Maschinenprogramme.Praktischer Gebrauch der Maschineninstruktionen.Vgl. mit höheren Programmiersprachen.Verbinden separat übersetzter Module.
Eine binäre Notation ist nicht mnemonisch & schlecht lesbar,manuelle Adressrechnungen und Anpassungen,unsystematische binäre Befehlscodierungen,manuelle Anpassung von Sprungdistanzen,kein Bezug auf externe Symbole.
Auch hexadezimale Notation ist ohne Kommentar äusserst unpraktisch:
dient dem Niederschreiben von Assemblerroutinen/-programmen,erlaubt Maschinenbefehle in mnemonischer Form.
Assemblierer:Hilfsrogramm, welches aus einem Assemblerprogramm ein Bindemodul produziert,
Assembler:der Begriff wird oft unscharf verwendet,manchmal das Hilfsprogramm zur Assemblierung,manchmal die Assemblersprache.
Binder/Linker:Dient zum Zusammenfügen getrennt übersetzter Objektmodule (Bibliotheken), Querverweise müssen aufgelöst werden,keine Prüfung auf Typenkonsistenz.
Lader:Laden eines Programms an die gewünschte Stelle im Hauptspeicher, Relozierung bedeutet Programme zu verschieben und Referenzen anzupassen,Verwaltung und Berücksichtigung von Relokationsinformation.
D.2.3 Binder bzw. LinkerIn MARS ist nur die Direktive .globl und .extern verfügbar.Anweisungen zum Exportieren und Importieren von Labels/Symbolen:
Exportierte Labels können von anderen Assemblerteilen importiert werden,Assembler erzeugt Bindemodule und Relokationsinformation,Labels verweisen auf Sprungziele und „Entry-Points“,ESD-Symbole können auch auf Daten verweisen,Link- oder Relozierungsinfo ist im => ESD.
External Symbol-Table – ESD:wird vom "Assemblierer" erzeugt,Ist im Objektmodul mit enthalten,exportierte Symbole werden von anderen referenziert,importierte Symbole werden aus dem Code referenziert,Externe Symboltabelle dient als Hilfstabelle für den Binder,Binder erzeugt Lademodul aus separat übersetzten Modulen, der Lader lädt Modul an die zur Laufzeit gewünschte Adresse,der Lader passt zudem nötigenfalls die Referenzen an (Relozierung).
D.2.5 Typische Dateiformate für Programme*.c, *.s, *.asm, *.java:
Quellprogramme für Compiler oder Assemblierer.
*.exe, *.com, *.sys ...:Lademodul für Windows.
*.dllDynamic Link Library für Windows, evtl. Link at run-time.
*.out , *.oklassisches UNIX-Format,Details sind evtl. plattformabhängig
*.COFF (Common Object File Format) Idee des einheitlichen Formats über alle Plattformen Headervariable spezifiziert Prozessorplattform Variante PE-COFF (Portable Executable ...): Windows Welt
*.ELF (Executable and Linkable Format) einheitliches Format für UNIX-Systeme definiert auch Systemaufrufe und deren Semantik (System-API)
Programmiersprache für maschinennahe Programmierung:mnemonische Kürzel für die einzelnen Maschinenbefehle,symbolische Namen für Programm- und Datenadressen,Notation für die Adressierungsarten und Konstanten,normalerweise eine Zeile pro Maschinenbefehl,sog. Makros anstelle von Prozeduren.
.text Main: add $1, $0, $31 # add register[0] and r[31] into r[1]
sub $1, $31, $0 # subtract r[0] from r[31] into r[1] slt $31, $0, $1 # set r[31] if r[0] < r[1] addi $7, $0, -20482 # add immediate+r[0] into r[7] sw $7, -20496($3) # store word from r[7] to Mem[$3+0xaff0] j Main # jump to instruction at Mem[Main]
Assemblierer
D.3.1 MARS – IDE IDE = Integrated Development Environment:
Texteditor, Assembler, Binder, Debugger ...
MARS = MIPS Assembler and Run-Time Simulator:http://www.cs.missouristate.edu/MARS/ Anzeige der Namen(Labels) für Sprungziele und Variablen,Anzeige der Instruktionen im Speicher,Anzeige der Prozessorregister,Anzeige des Datenspeichers,Text bedeutet hier Code.
D.3.2 Höhere Programmiersprachen im Vergleich:Wesentliche Erleichterung für Programmierarbeit:
Quelltext zum Beispiel in der Programmiersprache Java =>Typenkonzept für Zuweisungen & Prozeduraufrufe,mehr als ein Maschinenbefehl pro Statement,Compiler verwendet nicht alle Befehle,Geschwindigkeitsnachteil,Bessere Produktivität.
Entsprechendes Programm in Assemblersprache:auf die MIPS-CPU bezogene Instruktionskürzel,Gute Auslastung der vorhandenen Register,pro Zeile ein Maschinenbefehl,kein Typenkonzept.
Entsprechender Maschinencode:Daten & Code im Speicher festgelegt,Daten bei 0x10010000besondere Debugtechniken,keine Mnemonik.
# s imp l e MIPS prog r amm to in i t i a l i z e an ar r a y# P. Schu l t h e s s , 9.5.2009 .da t a # va r i a b l e s @ 10010000ar r : .wo rd 0:10 # 10 e lemen t s (not 11) . t e x t # code s ta r t s here la $7, ar r ($0) # "Load add r" , s ta r t index add i $8,$7,40 # se t s top i n de x add i $9,$0,0x41 # 'A ' i n t o r[9]loop : sw $9,0($7) # s to r e to memory add i $7,$7,4 # inc r emen t index beq $7,$8, f i n # te rm i na t e ? j loop # repea t
f i n : add i $2,$0, 10 # reques t ex i tsysca l l # tha t i s a l l
Quelltexte in Assemblersprache übersetzt der Assemblierer in Objektmodule:„Assembler“ bezeichnet oft die Sprache und oft das Übersetzerprogramm.
Zeilenorientierte Assemblerbefehle:Befehlszeilen werden in eine Maschineninstruktion übersetzt,Assemblerdirektiven bzw. Pseudobefehle steuern die Übersetzung.
Label: Die Programmausführung beginnt beim obligatorischen Label „main“,Label dienen als Bezeichner und beginnen nicht mit einer Ziffer,symbolische Marke im Text, abgeschlossen durch ":",wird mit der aktuellen Speicheradresse verbunden,delegiert Adressrechnung an den Assemblierer.
Bedeutung der Operationscodes (siehe Referenztabelle):Befehle mit einem Inline-Operanden (load, store, add-immediate ...),Sprungbefehle (jump absolute, branch on equal ...),Registerbefehle (add, shift, set less than ...).
Operanden: Registernamen, Adressen, Werte, Konstanten, Zeichenketten, Angaben zur Adressierungsart,z.B.
add i $8, $0, 'A 'sw $8, cap i t a l A($0)
Kommentare:dienen der Erläuterung durch den menschlichen Leser,eingeleitet durch ein '#',bis Ende der Zeile.
Zahlendarstellung in Assemblersprache:Dezimalzahlen: wie gewohnt, z.B. 3455 Hexadezimalzahlen: beginnen mit 0x , z.B. 0xAffe4711 Oktalzahlen: beginnen mit einer Null, z.B. 0030701
In MARS nicht möglich:Konstante Berechnungen: z.B. range * elementSizeBerechnung des Wertes zur Übersetzungszeit.
D.4.1 AssemblerdirektivenAssemblerdirektiven steuern den Übersetzungsvorgang:
Vereinbarung von Konstanten & Variablen,Plazierung von Daten- und Codebereichen,Vereinbarung von Sprungzielen ...
Assemblierung von Daten- und Codesegmenten:.data zeigt auf die nächste freie Stelle im Datenbereich,.text zeigt auf die nächste freie Stelle im Codebereich,Symboltabelle mit lokalen & globalen Bezeichnern,Assembler kennt nur 2 Bereiche,evtl. mehrere Module binden.
Initialwerte:.data zeigt zu Beginn auf 0x10010000,.text zeigt zu Beginn auf 0x00400000.
D.4.2 Assembler-Direktiven für die Segmentierung:. t e x t [add res s ]
nachfolgende Assemblierung in das Textsegment (normalerweise Code), Von einer Modifikation des Codesegmentes wird abgeraten,Fakultative Adresse bezeichnet die neue Adresse.
.da t a [add res s ]nachfolgende Assemblierung in das Datensegment. Fakultativ Datenadresse neu setzen,Ausführung von Werten aus dem Datensegment als Instruktionen ist nicht empfohlen.
.ex t e r n symbS i zeDer nachfolgende Label hat die Grösse symbSize (fakultativ),er liegt nicht im eigenen Modul.
.g l o b l symb später geladene Module können sich an den Label als externe Referenz verbinden,damit können separat übersetzte Module untereinander kommunizieren,Ein Typenkonzept gibt es nicht.
Sto r e (sw, sh, sb): sw $1,adr($17)speichert 32-Bit Wörter, 16-Bit Wörter oder Bytes aus rs an die gegebene Adressse,Adressenbildung aus rt und immediate Operand mit Vorzeichenerweiterung,D.h. Indizierung mit rt (Indizierung optional).
Load (lw, lu i , l hu , lbu . . .) : lw $1,adr($17)lädt 32-Bit Wörter, 16-Bit Wörter oder Bytes nach Register rt, Indizierung mit rs,load word signExtended, load upper-half of register, load halfword unsigned, load byte unsigned.
Immediate Arithmetik: addi $16,$17, iConstaddi – add immediateaddiu – add immediate unsignedandi – and immediate ...beq – branch on equal
bne – branch on not equallui – load upper immediateslti – set less than immediatesltiu – set less than imm. unsig.
Jeweils drei Operanden im R-Format:Zwei Input-Operanden, ein Resultat-Operand (Register r0 ist immer null),Verschiebungsdistanz für das Resultat (falls Shift-Befehl),Sekundärer Funktionscode.
seq – set if equalsgt – set if greaterslt – set less thansll – shift left logicalsrl – shift right logicalslrv – shift right logical varyingxor – exklusives Oder...u – für „unsigned“
D.6.1 Umsetzung einer Pascal if-Anweisung in Assemblersprache
program IfStmt(out);(* Pascal if-Anweisung P. Sch., 20.10.07*)var low: string; hig: string; res: integer;begin low:='easy'; hig:='life'; if low < hig then res:=6 else res:=7end.
# If-Anweisung in Assemblersprache# 11.05.2009, P. Schulthess
.data low: .ascii "easy"hig: .ascii "life"res: .word 0 .textmain: lw $8,low # var. low => r8 lw $9,hig # var. high =>r9 sltu $10,$8,$9 # (low<high =>r10 beqz $10,else # branch if falsethen: addi $11,$0,0x6 # set to 6 j endif # skip else clauseelse: addi $11,$0,0x7 # set to 7endif:sw $11,res($0) # store result addi $2,$0,10 # request exit syscall # that is all
Die Zweige der If-Anweisung werden aneinandergefügt:„then“-Zweig darf nicht in den „else“-Zweig hineinlaufen,Einmal muss in jedem Fall gesprungen werden,Sprünge behindern die flüssige Bearbeitung.
Umdenken von der Speicher- in die Registerebene:In der Maschine werden die Variablen nach Möglichkeit in Registern gehalten,Die Register $t0 bis $t9 sind meist ungesicherte temporäre Register,Diese dürften durch eine aufgerufene Prozedur zerstört werden.
Übersetzung eines in höherer Programiersprache vorliegenden Quelltextes:Eventuell Übersetzung in Assemblersprache und anschliessend Asssmblierung,Abweichende Codeerzeugungmuster je nach gewählter Optimierungsstufe,Evtl. Aufruf einer Laufzeitbibliothek für den Stringvergleich,Ein suboptimaler Compiler würde zweimal speichern,Handhabung von Strings oft sehr umständlich,Evtl. Conditional Move erzeugen.
Program cas(out); var arg, res: integer; begin arg:=3;
# Fallunterscheidung mit CASE bzw. SWITCH # 20.10.2007, P. Schulthess, einfaches Schema .text .globl main main: addi $8,$0,0x3 # get case argument slti $9,$8,0x0 # arg less than 0 ? bne $9,$0,else # argument is low slti $10,$8,0x4 # argument valid ? beq $10,$0,else # argument is high
Verzweigung über Sprungtabelle oder eine Folge von IF-Anweisungen.Abprüfen auf gültiges Argument in $8.Verzicht auf Tastatureingabe.Else-Fall auf nächster Seite.
addi $17,$zero,2 # variable for shiftingloop: sllv $16,$16,$17 # varying shift-amount in register
sw $16,pattern($0) # write back to main memoryj loop # jump back forever
Unbequeme Variablenadressierung in MARS:Der Mars-Simulator verbietet Datensegmente unterhalb 0x10000000,16-bit Offset in der lw-Instruktion kann nicht verwendet werden,Alle Variablen- oder Instruktions-Adressen sind 32-bit breit,Der Assemblierer verwendet Pseudo-Instruktionen,Eleganz der MIPS-Instruktionen geht verloren.
In MARS fehlt eine basisbezogene Adresserung, nicht jedoch in MIPS.
Leider verlangt MARS ein Datensegment über 0x10000000:lw, sw, la müssen damit zu Pseudo-Instruktionen werden:
.data 0x10010AFF # address will not fit into the 16 bit offsetpattern: .word 0x00000001 # single-bit mask
.text 0x400000main: lw $16,pattern # get bit pattern from main memory
addi $17,$zero,2 # variable for shiftingloop: sllv $16,$16,$17 # varying shift-amount in register 17
sw $16,pattern # write back to main memoryj loop # jump back forever
Als echte Instruktionsfolge ergibt sich:main: lui $1,0x1001 # load upper half of register 1
lw $16,$0x0aff,$1 # now 16-bit Offset is possibleaddi $17,$zero,2 # variable for shifting is 2
loop: sllv $16,$16,$17 # varying shift-amount in register 17lui $1,0x1001 # load uppe r ha l f o f reg i s t e r 1sw $16,$0x0aff,$1 # write back to main memoryj loop # jump back forever
D.7.3 Funktionsbezogene RegisterbenennungNamenskonvention für kooperierende Module:
verbesserte Mnemonik, Darstellung im MARS Registerfenster,$zero enthält immer Null, kann geschrieben werden,$at für Assemblierer reserviert (Pseudoinstruktionen),$v0..$v1 Funktionsresultat und arithmetische Ausdrücke,$a0..$a3 Parameter für einen Funktionsaufruf,$t0..$t7 ungesicherte temporäre Register,$s0..$s7 gesicherte temporäre Register (auch nach Funkt.),$t8..$t9 ungesicherte temporäre Register,$k0..$k1 reserviert für den Betriebssystemkern (rt),$gp Global pointer - zeigt auf globale Variablen,$sp Stack pointer - zeigt auf „Top of Stack“,$fp Frame pointer – zeigt auf aktuellen Stackframe,$ra Return address – Rückkehradresse aus Funktion,$f0-$f31 Gleitkommaregister – hier nicht diskutiert.
D.7.4 PrintSum – Ausgabe eines ResultatesEinschliesslich funktionsbezogene Registerbenennung.
# Summe der Elemente eines Vektors ausgeben# P. Schulthess, 1.5.2008 .Data vsize: .word 40vektor: .word 9,8,7,6,5,4,3,2,1,0 .Textmain: lw $t0,vsize($zero) # bytesize of vektorwhile: addi $t0,$t0,-4 # predecrement zlr in temp-0 lw $t1,vektor($t0) # load element from memory add $t2,$t2,$t1 # add element to $t2 (=sum) beqz $t0,fin # break if zlr is zero j while # iteratefin: addi $a0,$t2,0 # sum as parameter to print addi $v0,$zero,1 # integer-print syscall # OS/rt-service addi $v0,$zero,10 # terminate syscall # OS
D.8.1 AllgemeinHauptspeicherbereich, dessen eines Ende dynamisch wächst bzw. schrumpft.Verwendung des Kellers für:
Übergabe von Parametern an Unterprogramme,Rücksprungadressen bei Unterprogrammaufrufen,Zurückschneiden des Kellers nach Prozeduraufrufen,Sicherung von Registerinhalten bei Unterbrechungen,lokale Variablen in Unterprogrammen,temporäre Werte in Berechnungen !!
Registerkonvention für MIPS/DLX:Register 29 dient als Stapelzeiger/Stackpointer,Register 30 zeigt auf die lokalen Variablen,Register 31 enthält Rückkehradresse ...
Wachstumsrichtung des Kellers: Stack wächst Richtung der niedrigeren Adressen („von oben nach unten“),Stackpointer zeigt auf zuletzt eingefügtes Byte bzw. Wort,d.h. niedrigste gültige Adresse im Stack,d.h. "oberstes" Stackbyte.
der Keller wächst - meist zu niedrigeren Adressen hin,Indizierte Adressierung (MIPS ohne Autodekrement),Dekrementieren des Stackzeigers,"Oben" auf den Keller,Kellerüberlauf ?
Push-Operation:Stackzeiger $29 um 4 dekrementieren,1 Wort auf dem Stack einkellern,d.h. addi $sp,$sp , - 4und sw $t0 ,0($29)
Pop-Operation:Ein Wort vom Keller holen,Stackzeiger $29 um 4 inkrementieren, d.h. lw $t 1 ,0($sp) und add i $sp,$sp , +4
Ablauf:Hauptprogramm ruft dreimal die Prozedur "wSub" (Codeersparnis),"wSub" ruft die Laufzeitumgebung (Dateisystem) über Syscall,Run-time Support besorgt die Formatierung und die Ausgabe,Die Rückkehradresse wird in Register 31 ($ra) gespeichert,Parameter in Register 4 bzw. $a0 übergeben.
D.9.1 Vorteile der Unterprogrammtechnik:Codeökonomie:
Häufig benutzte Programmteile werden einmal geschrieben und mehrfach verwendet,Fremde Unterprogramme/Bibliotheken können vom Binder hinzugebunden werden, Unverzichtbare Abstraktionswirkung für höhere Programmiersprachen,Bequeme Speichervergabe und Speicherrückgabe.
Parameter und Ergebnisse: Übergabe wahlweise in Registern oder auf dem Stack möglich,Vorgegebene Parameterreihenfolge auf dem Stack,Registerkonvention bestimmt das Resultatregister,Leider oft divergierende Aufrufskonventionen.
Weitere Elemente auf dem Keller (optional):Dynamische & statische Prozedur-Verkettung,Klassendeskriptor & Objektreferenz,Rücksprungadresse der Prozedurlokale & temporäre Variablen,RegistersicherungFunktionswert ...
Java Programm als Modell für die Formulierung in Assemblersprache:. . .recur ( 7, 0xaffe ) ;. . . void recur ( int depth, int mark){ i f ( depth==0) return; else recur (depth- 1, mark); }. . .
Mehrere verschachtelte Stackframes werden aufgebaut:der Stackframe der aktuellen Prozedur wird über den Framepointer ($fp) gefunden,Framepointer=Basepointer (EBP für 32 Bit Intelx86 CPUs),Rückkehradresse zum Aufrufer einkellern aus $31/$ra,Referenz auf vorhergehenden Stackframe aus $fp,zu sichernde Register,lokale Variablen.
„mark“ dient der Wiedererkennung im Speicherabbild (in MARS).Abbruchbedingung nicht vergessen.
3 Stackframes auf dem Stack/Keller:Parameter hier in den Registern übergeben, nicht auf dem Keller,Return Address zeigt in den Codebereich,Frame Pointer zeigt in den Keller,„mal höher mal niedriger“.
Prozeduraufruf:Parameter in Register $a0.. legen,Prozedur-Aufruf mit Jump-And-Link Instruktion (j a l ). Die Instruktion legt die Rückkehradresse in das Register $31/$ra ab.
Prozedur-Prolog:Rückkehradresse auf dem Keller sichern (falls rekursive Situation),falls nötig alten Framepointer ($fp) auf dem Keller sichern (Dynamic Link),Register sichern, welche voraussichtlich durch unsere Prozedur zerstört werden,Stackzeiger in Register $29/$sp dekrementieren (Stack wächst hier nach unten).
Prozedur-Epilog:Stackzeiger inkrementieren, Stack schrumpft, Speicher wird freigegeben,Zerstörte Arbeitsregister wiederherstellen (entfällt hier),alten Frame/Base Pointer wiederherstellen ($30),Rückkehradresse in Register-31 bereitlegen,Rücksprung (j r – jump to register).
Konvention zur Registersicherung:Die aufgerufene Subroutine sichert die Register $16 bis $23 falls diese verändert werden,Zurückgegebener Funktionswert in Register $2 und $3 - $v0..$v1,Aktuelle Parameter in $4 bis $7 - $a0..$a3
Übersichtlicher für den Programmierer, aber weniger schnell ist die rekursive Variante:
stat i c int rF i bo( int N){ i f (N<3) return 1;
return rF i bo(N-1) + rF i b o(N-2);}
Allgemeine Bemerkungen:Die Rekursion auf dem Keller wird in der MIPS-Architektur leider etwas umständlich,MIPS als Beispiel für einen Rechner mit einfachen Befehlen & vielen Registern,Mikrocontroller haben im Gegensatz dazu nur wenige Register,aber viele Adressierungsmodi & spezielle Stackinstruktionen,Damit wird die µC-Programmierung „trickreicher“,Die Konzepte auf Assemblerebene sind ähnlich.
Unser aktuelles Ziel ist es, die didaktische Lücke zwischen Hardware und Programmiersprache zu schließen, und nicht die Programmierung von Mikrocontroller-Systemen zu vermitteln.
D.10.2 Rekursive Berechnung von Fibonacci-ZahlenRekursive Definition:
für alle n > 2: fibo(n) = fibo(n – 1) + fibo(n – 2);für n in {1,2}: fibo = 1;
Umsetzung in rekursive Unterprogrammaufrufe: Rekursionstiefe nur durch verfügbare Stackgröße beschränkt,Verkettungen & Rückkehradressen auf den Stack legen,Wiederverwendete Register im Keller sichern,Ergebnisrückgabe in einem Register,Parameterübergabe in Registern.
Maschinen mit wenig Registern (Intel x86, M6809 ...):Bei jedem Aufruf wird ein neuer, vollständiger Stackframe angelegt,Parameter werden typischerweise auf dem Keller übergeben,Operanden und Zwischenresultate meist auf dem Keller,Oft besondere Stack-Instruktionen (push-All ..).
Maschinen mit vielen Registern, z.B. DLX & MIPS:Die Berechnung erfolgt primär in den Registern,Nur bei Bedarf werden Register eingekellert.
publ ic stat i c void main(St r ing [ ] args ) {System.out.pr in t ln (F ibo (1 ) ) ;System.out.pr in t ln (F ibo (2 ) ) ;System.out.pr in t ln (F ibo (5 ) ) ;System.out.pr in t ln (F ibo (6 ) ) ;
}stat i c int Fibo( int N) {
i f (N<3) return 1;return Fibo(N- 1)+Fibo(N- 2);
}}
Die Formulierung in Java spiegelt direkt die Definition der Fibonacci-Reihe.Weniger übersichtlich ist hingegen die Formulierung in Assemblersprache.
D.10.4 Rekursive Fibonacci-Berechnung in AssemblerspracheEin Beispiel für Stackrekursion in Assemblersprache:
Etwas umständliche Abbruchbedingung,Framepointer kann hier entfallen.
Visualisierung im MARS IDE:$gp wird missbraucht, um den Stack im Datenfenster anzuzeigen,Stackframe wird auf 16 Bytes aufgefüllt zur besseren Visualisierung,Stackposition für $ra-Sicherung wird gelöscht, um die Visualisierung zu verbessern.
Direktive .globl :macht ein Label des aktuellen Moduls (Quell-Datei) für andere Module sichtbar,gilt für Variablennamen oder für Sprungadressen im Programmtext,Allozierung entweder im Daten- oder im Textsegment.
Direktive .extern :Alloziert einen Speicherbereich im externen Speichersegment ( typisch ab 0x10000000 ),Speicherbereich ist nicht typisiert, sondern nur mit Längenangabe versehen,macht den zugeordneten Label global sichtbar,nur nützlich für Variablenamen.
Programmfragment: .extern mnExt,4 # allocated in external segment, public .data .globl mnVar # allocated in data segment, public
mnVar: .word 0x00affe00 # global var as parameter for extInc
.extern xxVar,4 # allocated in external segment, public .extern mnExt,4 # allocated in external segment, public .data .globl mnVar # allocated in data segment, public
MnVar: .word 0x00affe00 # global var as parameter for extIncxxVar: .word 0x00affe04 # allocated in data segment, private
.textmain: jal extInc # invoke extInc as a subroutine
addi $2,$0,10 # parm for exit-syscall Syscall # exit
.extern bibEx,8 # allocated in external segment, public .extern xxVar,4 # declared but invisible, unused .data
xxVar: .word 0x00affe08 # private to bib-module, unused .text .globl extInc # our code but public
ExtInc: lw $t0,mnVar # load as global variable addi $v0,$t0,1 # increment the value (as result) sw $v0,mnVar # store the value back jr $ra # return from subroutine
BibDemoBib.asm
BibDemoMain.asm
D.12. Fazit
Höhere Sprachen:abstrahieren von der Maschinenarchitektur (Register, Opcodes ...), erlauben eine Konzentrierung auf den Algorithmus,oft suboptimale Codeerzeugung.
Assemblersprache:verbesserte Mnemonik gegenüber binärer Programmierung (Label, Formate),die volle Rechenleistung und alle CPU-Resourcen können genutzt werden,viele Details der Registernutzung und bei Aufrufen sind zu beachten,Wechselwirkung zwischen Architektur & Programm wird sichtbar,Konventionen zum Binden und zum Systemaufruf beachten.
Pseudo-Instruktionen und Makros:Spracherweiterung für den Assemblerprogrammierer,erlauben eine gewisse Konfigurierbarkeit des Programmes,können unwichtige Details aus dem Haupttext wegdefinieren.
MIPS Architektur:Interrupts & Gleitkomma-Verarbeitung haben wir hier weggelassen,einfacher Instruktionssatz mit vielen Registern,effiziente Implementierung möglich.