Was ist Assembler?
Ein Prozessor versteht nur Maschinencode: Zahlen, die Befehle darstellen. Assembler ist die lesbare Schreibweise dafür. Jede Zeile entspricht fast immer genau einem Prozessorbefehl, zum Beispiel mov (kopieren) oder add (addieren). Ein Assembler (das Programm, z. B. NASM) übersetzt den Text in Maschinencode.
Warum Assembler lernen?
- Du verstehst, wie Computer wirklich rechnen: Register, Speicher, Stack, Systemaufrufe
- Wichtig für Betriebssysteme, Treiber, Bootloader, Compiler, eingebettete Systeme
- Grundlage für Reverse Engineering und Sicherheitsforschung (Schadsoftware analysieren, Exploits verstehen)
- Hilft beim Debuggen und Optimieren von Hochsprachen-Code
Dieser Kurs behandelt x86-64 unter Linux mit der NASM-Syntax (Intel-Schreibweise). Andere Architekturen (ARM, RISC-V) funktionieren nach demselben Prinzip mit anderen Befehlen.
Werkzeuge
nasm -f elf64 hallo.asm -o hallo.o # Assemblieren
ld hallo.o -o hallo # Binden
./hallo # Ausführen
objdump -d -M intel hallo # Maschinencode ansehen (Disassemblieren)
gdb ./hallo # DebuggerDas erste Programm
section .data
text db "Hallo, Welt!", 10 ; 10 = Zeilenumbruch
laenge equ $ - text ; Länge berechnen
section .text
global _start
_start:
mov rax, 1 ; Systemaufruf Nr. 1: write
mov rdi, 1 ; Ziel: Dateideskriptor 1 = stdout
mov rsi, text ; Adresse des Textes
mov rdx, laenge ; Anzahl der Bytes
syscall ; Kernel aufrufen
mov rax, 60 ; Systemaufruf Nr. 60: exit
xor rdi, rdi ; Rückgabewert 0
syscallHallo, Welt!
So ist das Programm aufgebaut:
| Teil | Bedeutung |
|---|---|
section .data | initialisierte Daten (Texte, Zahlen) |
section .bss | Speicher ohne Anfangswert (Puffer) |
section .text | der Programmcode |
global _start | Einstiegspunkt für den Linker |
_start: | Label: ein Name für eine Adresse |
db, dw, dd, dq | Daten definieren: 1, 2, 4, 8 Bytes |
equ | Konstante |
; ... | Kommentar |
Ein Befehl hat die Form befehl ziel, quelle (Intel-Syntax: Ziel zuerst). Anders als in Hochsprachen läuft das Programm einfach Zeile für Zeile; am Ende musst du exit aufrufen, sonst läuft der Prozessor in zufälligen Speicher und stürzt ab.
Systemaufrufe
Programme sprechen mit dem Betriebssystem über Systemaufrufe (syscalls): Nummer in rax, Argumente in rdi, rsi, rdx, r10, r8, r9, dann syscall.
| Nr. (rax) | Name | Argumente |
|---|---|---|
| 0 | read | rdi = fd, rsi = Puffer, rdx = Länge |
| 1 | write | rdi = fd, rsi = Puffer, rdx = Länge |
| 2 | open | rdi = Pfad, rsi = Flags, rdx = Modus |
| 3 | close | rdi = fd |
| 60 | exit | rdi = Exit-Code |
So führst du den Code aus: Datei hallo.asm speichern, mit nasm -f elf64 hallo.asm übersetzen und mit ld hallo.o -o hallo binden, dann ./hallo (Linux, NASM-Syntax).
Merke
- Assembler = lesbare Form des Maschinencodes, eine Zeile ≈ ein Befehl
- NASM assembliert,
ldbindet; Programme starten bei_start - Abschnitte
.data,.bss,.text; Labels,db/dq,equ - Systemaufrufe: Nummer in
rax, Argumente inrdi,rsi,rdx, dannsyscall - Intel-Syntax:
befehl ziel, quelle
Aufgabe
Ändere den Text und übersetze das Programm neu. Gib danach zwei Zeilen aus.