Befehle im Überblick
| Gruppe | Befehle |
|---|---|
| Daten bewegen | mov, movzx, movsx, lea, xchg, push, pop, cmov* |
| Rechnen | add, sub, inc, dec, neg, imul, mul, idiv, div, adc, sbb |
| Logik/Bits | and, or, xor, not, shl, shr, sar, rol, ror, bt, test |
| Vergleich | cmp, test, set* |
| Sprünge | jmp, je/jne, jl/jle/jg/jge, jb/ja, js, jc, loop |
| Funktionen | call, ret, leave, enter |
| Strings | movsb, stosb, lodsb, scasb, cmpsb, rep, repe |
| System | syscall, int 0x80, cpuid, rdtsc, nop, hlt |
| Fließkomma/SIMD | movsd, addsd, mulsd, sqrtsd, cvtsi2sd, movdqu, paddd, addps |
Register-Schnellübersicht
Allgemein: rax rbx rcx rdx rsi rdi rbp rsp r8-r15
32 Bit: eax ebx ecx edx esi edi ebp esp r8d-r15d
16/8 Bit: ax bx cx dx / al bl cl dl (ah bh ch dh)
Sonstige: rip (Befehlszeiger) rflags (Flags) xmm0-xmm15 / ymm0-ymm15
System-V-Argumente: rdi rsi rdx rcx r8 r9 (Rückgabe: rax)
Syscall-Argumente: rax=Nr rdi rsi rdx r10 r8 r9 (Rückgabe: rax)
Callee-saved: rbx rbp r12 r13 r14 r15Bedingte Sprünge nach cmp a, b
| Bedingung | vorzeichenbehaftet | vorzeichenlos |
|---|---|---|
| a == b | je | je |
| a != b | jne | jne |
| a < b | jl | jb |
| a <= b | jle | jbe |
| a > b | jg | ja |
| a >= b | jge | jae |
Typische Muster
section .bss
puffer resb 32
section .text
global _start
_start:
xor rax, rax ; rax = 0
mov rax, 5
lea rbx, [rax + rax*4] ; rbx = rax * 5 (ohne imul)
mov rax, rbx
call ausgabe_zahl ; 25
mov rax, 17
and rax, 15 ; rax mod 16
call ausgabe_zahl ; 1
mov rax, 100
shr rax, 2 ; rax / 4
call ausgabe_zahl ; 25
mov rax, 8
mov rbx, 3
xchg rax, rbx ; tauschen
call ausgabe_zahl ; 3
mov rax, 5
mov rbx, 9
cmp rax, rbx
cmovl rax, rbx ; Maximum ohne Sprung
call ausgabe_zahl ; 9
mov rax, 60
xor rdi, rdi
syscall
; --- Hilfsroutine: gibt die Zahl in RAX dezimal aus (mit Zeilenumbruch), alle Register bleiben erhalten ---
ausgabe_zahl:
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
mov rcx, puffer + 20 ; Ende des Puffers
mov byte [rcx], 10 ; Zeilenumbruch ans Ende
mov rbx, 10
.schleife:
xor rdx, rdx
div rbx ; RAX = RAX / 10, RDX = Rest
add dl, '0' ; Ziffer in ASCII umwandeln
dec rcx
mov [rcx], dl
test rax, rax
jnz .schleife
mov rax, 1 ; write
mov rdi, 1
mov rsi, rcx
lea rdx, [puffer + 21]
sub rdx, rcx
syscall
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax
retAusgabe
25 1 25 3 9
Typische Fehler
| Symptom | Ursache |
|---|---|
Segmentation fault | Zugriff auf ungültige Adresse; [ ] vergessen oder Zeiger nicht gesetzt |
| Programm läuft ins Leere und stürzt ab | exit-Systemaufruf fehlt |
| Falsche Zahl beim Rechnen | Teilregister (eax) füllt die oberen Bits mit 0; rdx vor div nicht gelöscht |
div löst "Floating point exception" aus | Division durch 0 oder Quotient passt nicht in rax |
| Stack zerstört | push/pop nicht ausgeglichen |
error: symbol 'x' not defined | Label vergessen oder nicht global |
| Falsche Reihenfolge der Operanden | Intel: mov ziel, quelle (AT&T-Syntax ist umgekehrt!) |
| Ausgabe fehlt | write mit falscher Länge oder falschem Dateideskriptor |
| Vorzeichen falsch | jl und jb verwechselt (vorzeichenbehaftet / -los) |
AT&T- und Intel-Syntax
GNU-Werkzeuge (gcc -S, objdump ohne Option) zeigen standardmäßig die AT&T-Syntax: Quelle zuerst, Register mit %, Konstanten mit $.
Intel (NASM): mov rax, 5 add rax, [rbx + 8]
AT&T (GAS): movq $5, %rax addq 8(%rbx), %raxWeiterlernen
- Intel/AMD-Handbücher (Intel SDM), Agner Fog "Optimizing Assembly" (agner.org/optimize)
- NASM-Handbuch (nasm.us/doc), Programming from the Ground Up, x86-64 Assembly Language Programming with Ubuntu
- Übungen: pwn.college, OverTheWire, Crackmes.one, Compiler Explorer (godbolt.org)
- Wiki dieser Seite: Artikel zu Prozessoren, Sicherheit und Reverse Engineering
Merke
- Intel-Syntax:
befehl ziel, quelle; Systemaufrufe überrax+syscall - Sprünge nach
cmp: vorzeichenbehaftetjl/jg, vorzeichenlosjb/ja - Funktionen: System-V-Konvention, Stack-Rahmen, Callee-saved-Register beachten
- Werkzeuge:
nasm,ld,objdump,gdb,strace, Compiler Explorer