Assembler verstehen: Befehle, Register, Schleifen
Assemblersprache stellt Maschinenbefehle mit lesbaren Kürzeln wie MOV und ADD dar. Ein Assembler übersetzt diese Befehle in den Maschinencode einer bestimmten Prozessorarchitektur.
Auf dieser Seite lernst du, eine kurze Befehlsfolge zu verfolgen und eine einfache Schleife zu erklären.
Hake ab, was du schon kannst — und komm am Ende hierher zurück!
Vom lesbaren Befehl zum Maschinencode
Eine CPU führt Maschinenbefehle aus, die als Bitmuster gespeichert sind. Assemblersprache ersetzt solche schwer lesbaren Bitmuster durch kurze symbolische Namen, sogenannte Mnemoniken. ADD steht beispielsweise für eine Addition.
Assemblersprache
Assemblersprache ist eine maschinennahe, symbolische Darstellung von CPU-Befehlen. Ihre Befehle und ihre genaue Schreibweise hängen von der Prozessorarchitektur und vom verwendeten Werkzeug ab.
Assembler
Ein Assembler ist ein Übersetzungsprogramm. Er wandelt Assemblersprache in Maschinencode oder in eine Objektdatei um.
Das Wort „Assembler“ wird im Alltag manchmal auch für die Sprache verwendet. Genau genommen unterscheidest du jedoch zwischen Assemblersprache und dem Assembler als Programm.
Ein Assembler erledigt mehr als das bloße Ersetzen von Befehlsnamen. Er kann unter anderem:
- Mnemoniken in passende Opcodes übersetzen,
- symbolische Namen durch Adressen ersetzen,
- zur Übersetzungszeit bekannte Ausdrücke berechnen,
- Kommentare ignorieren,
- unzulässige Befehle zurückweisen,
- Makros verarbeiten und
- Maschinencode oder Objektdateien erzeugen.
Assemblersprache ist der symbolische Quelltext. Der Assembler ist das Programm, das diesen Quelltext übersetzt.
Register und einfache Befehle
Ein Register ist ein kleiner Speicherplatz direkt in der CPU. Befehle können Werte in Register schreiben, Werte verändern oder Ergebnisse zwischen Registern übertragen.
Die folgenden Beispiele verwenden eine vereinfachte Lehrsyntax. Sie zeigt die Grundidee, ist aber kein vollständiger x86-Dialekt.
| Befehl | Wirkung |
|---|---|
MOV A 5 | Schreibe den Wert 5 in Register A. |
ADD C A | Addiere den Wert aus A zu C und speichere das Ergebnis in C. |
DEC B | Vermindere den Wert in B um 1. |
JNZ Loop | Springe zum Label Loop, wenn das Zero-Flag nicht gesetzt ist. |
RET | Kehre im vereinfachten Aufgabenmodell aus der Befehlsfolge zurück. |
Ein Label ist ein Name für eine Stelle im Programm. Ein Sprungbefehl kann die Ausführung an diesem Namen fortsetzen.
Betrachte diese drei Befehle:
text MOV A 5 MOV C 0 ADD C A
Nach dem ersten Befehl gilt A = 5. Danach wird C auf 0 gesetzt. ADD C A berechnet schließlich C = 0 + 5. Am Ende steht daher 5 in C.
Wie eine Schleife entsteht
Hochsprachen besitzen fertige Konstruktionen wie for oder while. Auf Maschinenebene entsteht eine Schleife aus einfachen Befehlen:
- Ein Zähler erhält einen Anfangswert.
- Der Schleifenrumpf verarbeitet Daten.
- Der Zähler wird verändert.
- Ein bedingter Sprung entscheidet, ob die Schleife wiederholt wird.
Viele Rechenbefehle verändern Flags. Flags sind einzelne Zustandsmerkmale der CPU. Das Zero-Flag zeigt an, ob das Ergebnis einer passenden Operation null war. JNZ bedeutet „springe, wenn nicht null“ und prüft dieses Flag.
Ein bedingter Sprung prüft nicht allgemein „den Wert der letzten Zeile“. Er wertet bestimmte Flags aus, die ein vorheriger Befehl gesetzt hat. Welche Flags verändert werden, hängt vom jeweiligen Befehl ab.
Nun verfolgen wir eine vollständige Schleife:
```text MOV A 5 MOV B 7 MOV C 0
Loop: ADD C A DEC B JNZ Loop RET ```
A enthält den Wert 5. B zählt die Schleifenrunden. C sammelt die Summe.
| Runde | C nach ADD C A | B nach DEC B | Noch einmal? |
|---|---|---|---|
| 1 | 5 | 6 | ja |
| 2 | 10 | 5 | ja |
| 3 | 15 | 4 | ja |
| 4 | 20 | 3 | ja |
| 5 | 25 | 2 | ja |
| 6 | 30 | 1 | ja |
| 7 | 35 | 0 | nein |
Die Addition wird siebenmal ausgeführt. Deshalb gilt:
$$C = 7 \cdot 5 = 35$$
Die Schleife berechnet also eine Multiplikation durch wiederholte Addition.
Beim Verfolgen einer Schleife notierst du nach jeder Runde alle Register, die verändert wurden. So erkennst du sowohl das Zwischenergebnis als auch die Abbruchbedingung.
Warum Assembler hardwarenah und wenig portabel ist
Prozessorarchitekturen legen fest, welche Maschinenbefehle, Register und Kodierungen verfügbar sind. Ein Assembler muss daher zur Zielarchitektur passen. Auch Werkzeuge für dieselbe Prozessorfamilie können unterschiedliche Schreibweisen und Makros verwenden.
Ein Cross-Assembler läuft auf einer Hostplattform, erzeugt aber Code für eine andere Zielplattform. Das ist beispielsweise bei der Entwicklung für Mikrocontroller nützlich.
Ein Disassembler geht in die Gegenrichtung: Er stellt Maschinencode wieder als Assemblersprache dar. Verlorene Kommentare und ursprüngliche symbolische Namen kann er jedoch nicht zuverlässig zurückholen.
Assembler bietet direkten Zugriff auf maschinennahe Möglichkeiten. Dafür entstehen klare Grenzen:
- Der Code ist stark an Architektur und Syntaxumgebung gebunden.
- Wartung und Fehlersuche verlangen genaues Prozessorwissen.
- Ein Wechsel der Zielarchitektur erfordert häufig Anpassungen.
- Die einfache Zuordnung „eine Anweisung gleich ein Maschinenbefehl“ gilt bei Makros nicht uneingeschränkt.
Hochsprachen verbergen viele Hardwaredetails und lassen sich deshalb meist leichter übertragen. Assembler wird heute vor allem dort eingesetzt, wo direkter Hardwarezugriff oder besondere Kontrolle notwendig oder nützlich ist. Inline-Assembler kann solche Abschnitte in ein Hochsprachenprogramm einbetten.
Karteikasten
Überlege zuerst selbst und drehe die Karte anschließend zum Prüfen um.
Alles auf einen Blick
- Assembler
- übersetzt Assemblersprache in Maschinencode
- erzeugt Code für eine Zielarchitektur
- Assemblersprache
- verwendet Mnemoniken und Operanden
- arbeitet mit Registern und Speicher
- Kontrollfluss
- Labels markieren Sprungziele
- Flags steuern bedingte Sprünge
- Schleife
- verarbeitet Daten
- verändert einen Zähler
- endet bei erfüllter Abbruchbedingung
- Grenzen
- architekturabhängig
- wartungsintensiv
Abschluss-Check
Du hast den Kern verstanden, wenn du eine Befehlsfolge registerweise verfolgen, die Sprungentscheidung erklären und die Architekturabhängigkeit begründen kannst.
Mit Google fortfahren