cmp und bedingte Sprünge
cmp a, b rechnet a - b nur für die Flags. Danach springt ein bedingter Sprung, wenn die Bedingung stimmt, sonst läuft das Programm einfach weiter:
| Sprung | Bedingung | Bedeutung |
|---|---|---|
je / jz | ZF = 1 | gleich / null |
jne / jnz | ZF = 0 | ungleich |
jl / jg | vorzeichenbehaftet | kleiner / größer |
jle / jge | vorzeichenbehaftet | kleiner-gleich / größer-gleich |
jb / ja | vorzeichenlos | below / above |
jmp | immer | unbedingter Sprung |
section .bss
puffer resb 32
section .text
global _start
_start:
mov rax, 7
cmp rax, 10
jl .kleiner
mov rbx, 0
jmp .weiter
.kleiner:
mov rbx, 1 ; rax ist kleiner als 10
.weiter:
mov rax, rbx
call ausgabe_zahl
; Maximum von zwei Zahlen
mov rax, 15
mov rbx, 42
cmp rax, rbx
jge .rax_ist_max
mov rax, rbx ; rbx ist größer
.rax_ist_max:
call ausgabe_zahl
; Betrag (abs)
mov rax, -17
test rax, rax ; setzt Flags wie "and rax, rax"
jns .positiv
neg rax
.positiv:
call ausgabe_zahl
; gerade oder ungerade?
mov rax, 27
test rax, 1 ; unterstes Bit
jz .gerade
mov rax, 1 ; ungerade
jmp .fertig
.gerade:
mov rax, 0
.fertig:
call ausgabe_zahl
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
1 42 17 1
Die Namen mit Punkt (.kleiner) sind lokale Labels, die zum letzten globalen Label gehören. So kannst du .schleife mehrfach in verschiedenen Routinen verwenden.
Schleifen
Eine Schleife ist ein Zähler, eine Marke am Anfang und ein bedingter Sprung zurück:
section .bss
puffer resb 32
section .text
global _start
_start:
; Zählen von 1 bis 5
mov rcx, 1
.zaehlen:
mov rax, rcx
call ausgabe_zahl
inc rcx
cmp rcx, 5
jle .zaehlen
; Summe 1 bis 100
xor rax, rax
mov rcx, 100
.summe:
add rax, rcx
dec rcx
jnz .summe ; solange rcx nicht 0
call ausgabe_zahl
; Fakultät von 10
mov rax, 1
mov rcx, 10
.fak:
imul rax, rcx
loop .fak ; loop: rcx verringern, springen solange rcx != 0
call ausgabe_zahl
; Fibonacci: die ersten 10 Zahlen
mov rax, 0
mov rbx, 1
mov rcx, 10
.fib:
push rax
call ausgabe_zahl
pop rax
mov rdx, rax
add rdx, rbx
mov rax, rbx
mov rbx, rdx
dec rcx
jnz .fib
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
1 2 3 4 5 5050 3628800 0 1 1 2 3 5 8 13 21 34
Verschachtelte Schleifen: Primzahlen
section .bss
puffer resb 32
section .text
global _start
_start:
mov r8, 2 ; Kandidat
.kandidat:
mov r9, 2 ; Teiler
.teiler:
mov rax, r9
imul rax, r9
cmp rax, r8 ; teiler^2 > kandidat? dann prim
jg .ist_prim
mov rax, r8
xor rdx, rdx
div r9
test rdx, rdx
jz .naechster ; Rest 0 → keine Primzahl
inc r9
jmp .teiler
.ist_prim:
mov rax, r8
call ausgabe_zahl
.naechster:
inc r8
cmp r8, 40
jle .kandidat
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
2 3 5 7 11 13 17 19 23 29 31 37
Merke
cmpvergleicht,testprüft Bits; danachje/jne/jl/jg/jle/jge(vorzeichenbehaftet),jb/ja(vorzeichenlos)jmpspringt immer; Labels markieren Ziele,.namesind lokal- Schleife: Zähler, Label,
dec+jnz(oderloop) if/elseundwhilesind in Assembler nur Sprungmuster
Aufgabe
Zähle die Zahlen von 1 bis 100 durch und gib nur die durch 7 teilbaren aus.