Was ist Assembler und wie kann ich es lernen?
Assembler ist bekannt als wohl die ursprünglichste aller Programmiersprachen und wird häufig synonym mit “Maschinensprache” benutzt. Assembler ist aber nicht gleich Assembler. Welche Unterschiede es zwischen verschiedenen Assemblern, Maschinensprache und anderen Programmiersprachen gibt, erfährst Du hier.
Assemblersprache: Was ist Assembler?
Ein in Assemblersprache geschriebenes Programm besteht aus einer Reihe von Mnemonic-Prozessor-Anweisungen und Meta-Statements (bekannt als Direktiven, Pseudo-Instruktionen und Pseudo-Ops), Kommentaren und Daten. Assembler-Sprachanweisungen bestehen normalerweise aus einem Opcode-Mnemonic gefolgt von einer Liste von Daten, Argumenten oder Parametern. Diese werden von einem Assembler (“Montierer”) in maschinensprachliche Anweisungen übersetzt bzw. “montiert”, die in den Speicher geladen und ausgeführt werden können. Assembler zu lernen kann auch für Entwickler reizvoll sein, die primär mit sogenannten Hochsprachen arbeiten, da Assembler Befehle oft Aufschluss darüber geben, wie eine Hochsprache letztendlich übersetzt wird, bis man ein ausführbares Programm erhält.
Einfache wichtige Assembler Befehle
Zum Beispiel weist der folgende Befehl einem x86 / IA-32-Prozessor an, einen unmittelbaren 8-Bit-Wert in ein Register zu verschieben. Der Binärcode für diese Anweisung ist 10110, gefolgt von einer 3-Bit-Kennung, die das zu verwendende Register bezeichnet. Die Kennung für das AL-Register ist 000, daher lädt der folgende Maschinencode das AL-Register mit den Daten 01100001.
10110000 01100001
Dieser binäre Computercode kann für Menschen etwas lesbarer gemacht werden, indem er wie folgt in hexadezimaler Form ausgedrückt wird.
B0 61
Hier bedeutet B0 ‘Kopie des folgenden Wertes in AL verschieben’ und 61 ist eine hexadezimale Darstellung des Wertes 01100001, der 97 in Dezimal entspricht. Die Assemblersprache für die 8086-Familie stellt den mnemonischen MOV (eine Abkürzung von move) für Anweisungen wie diesen bereit, so dass der obige Maschinencode wie folgt in Assemblersprache geschrieben werden kann, falls erforderlich mit einem erläuternden Kommentar nach dem Semikolon. Dies ist viel einfacher zu lesen und zu behalten.
MOV AL, 61h ; 97 dezimal (61 hex) in AL laden
In einigen Assemblersprachen kann dieselbe Abkürzung wie beispielsweise MOV für eine Gruppe verwandter Anweisungen zum Laden, Kopieren und Verschieben von Daten verwendet werden, unabhängig davon, ob es sich um direkte Werte, Werte in Registern oder solche in Speicherstellen, die auf die Werte in Registern zeigen, handelt. Andere Assembler können separate Opcode-Mnemonics verwenden, wie beispielsweise L für “Speicher zu Register verschieben”, ST für “Register in Speicher verschieben”, LR für “Register in anderes Register verschieben”, MVI für “unmittelbaren Operanden in Speicher verschieben” und Weitere.
Der x86-Opcode 10110000 (B0) kopiert einen 8-Bit-Wert in das AL-Register, während 10110001 (B1) ihn in CL und 10110010 (B2) in DL kopiert.
Assembler-Befehle für diese Fälle würden wie folgt aus sehen:
MOV AL, 1h; Direktwert 1 in AL laden MOV CL, 2h; Direktwert 2 in CL laden MOV DL, 3h; Direktwert 3 in DL laden
Die Syntax von MOV kann auch komplexer sein, wie in dem folgenden Beispiele gezeigt:
MOV EAX, [EBX]; Die 4 Bytes im Speicher an der in EBX enthaltenen Speicheradresse in EAX verschieben MOV [ESI + EAX], CL; Den Inhalt von CL in das Byte an der Adresse ESI + EAX verschieben
In jedem Fall wird die MOV-Mnemonic von einem Assembler direkt in einen Opcode in den Bereichen 88-8E, A0-A3, B0-B8, C6 oder C7 übersetzt, und der Programmierer muss dabei nicht wissen in welchen, oder sich daran erinnern.
Das Umwandeln und “Disassemblen” von Assemblersprache
Das Umwandeln der Assemblersprache in Maschinencode ist die Aufgabe eines Assemblers, umgekehrt kann die Umwandlung zumindest teilweise durch einen Disassembler erreicht werden. Im Gegensatz zu Hochsprachen gibt es eine Eins-zu-Eins-Entsprechung zwischen vielen einfachen Assembly-Anweisungen und Maschinensprachen-Anweisungen. In einigen Fällen kann ein Assembler jedoch Pseudoanweisungen (im Wesentlichen Makros) bereitstellen, die sich nach der Umwandlung durch einen Assembler in mehrere Maschinensprachanweisungen erweitern, um oft benötigte Funktionalität bereitzustellen.
Zum Beispiel kann ein Assembler für eine Maschine, der ein Befehl “Verzweige wenn größer oder gleich” fehlt, eine entsprechende Pseudoanweisung bereitstellen, die auf die dieser Maschine bekannten Befehle “setze wenn kleiner als” und “verzweige wenn Null (als Ergebnis der set-Anweisung)” erweitert beziehungsweise übersetzt wird. Die meisten voll funktionsfähigen Assembler bieten auch eine reichhaltige Makrosprache (siehe unten), die von Anbietern und Programmierern verwendet wird, um komplexere Code- und Datensequenzen zu erzeugen.
Jede Computerarchitektur hat ihre eigene Maschinensprache
Jede Computerarchitektur hat ihre eigene Maschinensprache. Computer unterscheiden sich in der Anzahl und Art der unterstützten Operationen, in Größe und Anzahl ihrer Register und in der Art wie Daten im Speicher repräsentiert werden. Obwohl die meisten Universalcomputer im wesentlichen die gleiche Funktionalität ausführen können, bestehen durchaus signifikante Unterschiede in der Art und Weise, wie das genau passiert. Die entsprechenden Assemblersprachen spiegeln diese plattformabhängigen Unterschiede wieder. Assembler lernen hat damit auch immer etwas mit der Architektur zu tun, für die Du entwickeln willst.
Für einen bestimmten Befehlssatz können mehrere Sätze von Mnemonikoder Assembler-Befehlen existieren, die typischerweise in verschiedenen Assembler-Programmen Anwendung finden. In diesen Fällen ist der am häufigsten verwendete Typ der vom Hersteller ausgelieferte und in dessen Dokumentation beschriebene.
Syntax von Assemblersprachanweisungen
Assembler Befehle werden eine Anweisung pro Zeile eingegeben. Jedes Statement folgt dem folgenden Format:
[Label] Befehl [Operanden] [; Kommentar]
Die Felder in den eckigen Klammern sind optional. Ein Basisbefehl besteht aus zwei Teilen, der erste ist der Name des Befehls (oder des Mnemonic), der ausgeführt werden soll, und der zweite sind die Operanden oder die Parameter des Befehls. Im Folgenden siehst Du einige Beispiele für typische Assembler-Befehle:
INC COUNT; Erhöhe die Speichervariable COUNT MOV TOTAL, 48; Übertrage den Wert 48 in die Speichervariable TOTAL ADD AH, BH; Trage den Inhalt des BH-Registers in das AH-Register ein AND MASK1, 128 ; Führe eine AND Operation mit der Variable MASK1 und 128 durch ADD MARKS, 10 ; Addiere 10 zur Variable MARKS MOV AL, 10 ; Übertrage den Wert 10 in das AL Register
Weitere Assembler Befehle: Hello World
Genau wie in den meisten anderen Programmiersprachen bietet es sich beim Assembler lernen an, zunächst mit einem Hello World-Programm zu beginnen. Dies könnte zum Beispiel wie folgt aussehen:
section .text global _start ;Deklaration für Linker _start: ; Entry Point für den Linker mov edx,len ;Nachrichtenlänge mov ecx,msg ;Zu schreibende Nachricht mov ebx,1 ;File Descriptor (stdout) mov eax,4 ;System Call Nummer(sys_write) int 0x80 ;Kernel Aufruf mov eax,1 ;System Call Nummer (sys_exit) int 0x80 ;Kernel Aufruf section .data msg db 'Hello, world!', 0xa ;Ausgabestring len equ $ - msg ;lLänge des Strings
Assembler lernen – Wo fange ich an?
Der einzige Weg, Assembler wirklich zu lernen, ist Assembler zu schreiben. Schreibe also Assembler-Programme. Du könntest Programme schreiben, während Du an einem Einsteiger-Buch über Assembler arbeitest.
Bevor man damit beginnt, Code zu schreiben, ist es immer eine gute Idee, zuerst die Sprache selbst zu verstehen. Es gibt eine Menge an verfügbaren Ressourcen, die von Lehrbüchern bis zu Online-Anleitungen reichen.
Zu Beginn ist es auch wichtig, grundlegende Begriffe zu lernen. Zum Beispiel möchtest Du wissen, dass eine IDE (integrierte Entwicklungsumgebung) eine Codierschnittstelle bereitstellt, die Dinge wie Textbearbeitung, Debugging und Kompilierung beinhaltet. Vielleicht möchtest Du auch besser verstehen, wie die Assemblierung tatsächlich funktioniert, wie etwa die Tatsache, dass “Register” die Nummern sind, die dem Programmcode zugeordnet sind. Ein besseres Verständnis der Terminologie wird es Dir erleichtern, den Code-Schreibprozess selbst zu erlernen.
Überlege Dir auch, ob Assembler tatsächlich das ist was Du lernen willst und ob Assembler lernen für Deine Zwecke am besten geeignet ist. Denke daran, dass es eine Reihe von Programmiersprachen gibt, darunter auch einige, die weit mehr Funktionen bieten als Assembler. Es gibt jedoch noch eine Reihe von Anwendungen, für die die Assemblierung nützlich ist – von der Erstellung eigenständiger ausführbarer Dateien für Telefon-Firmware und Steuersysteme für Geräte aller Art bis zur Entwicklung bestimmter prozessorspezifischer Anweisungen.