Daten im Speicher
Der Arbeitsspeicher besteht aus nummerierten Bytes. Ein Label in .data steht für eine Adresse; eckige Klammern [...] bedeuten Inhalt an dieser Adresse (wie ein Zeiger dereferenzieren).
| Direktive | Größe | Beispiel |
|---|---|---|
db | 1 Byte | zeichen db 'A' |
dw | 2 Byte | kurz dw 1000 |
dd | 4 Byte | mittel dd 100000 |
dq | 8 Byte | gross dq 9000000000 |
resb/resq (in .bss) | reservieren | puffer resb 64 |
section .data
zahl dq 41
liste dq 10, 20, 30, 40, 50
bytes db 1, 2, 3
text db "Assembler", 0
section .bss
puffer resb 32
ergebnis resq 1
section .text
global _start
_start:
mov rax, [zahl] ; Inhalt laden
inc rax
mov [zahl], rax ; zurückschreiben
mov rax, [zahl]
call ausgabe_zahl
mov rax, liste ; Adresse (ohne Klammern)
mov rbx, [rax] ; erstes Element
mov rax, [liste + 8] ; zweites Element (jedes ist 8 Byte)
call ausgabe_zahl
lea rsi, [liste] ; lea berechnet die Adresse, ohne zu lesen
mov rax, [rsi + 2*8] ; drittes Element (Basis + Index*Größe)
call ausgabe_zahl
movzx rax, byte [bytes + 2] ; 1 Byte laden und auf 64 Bit erweitern
call ausgabe_zahl
mov qword [ergebnis], 123
mov rax, [ergebnis]
call ausgabe_zahl
mov rax, text
movzx rax, byte [text] ; erster Buchstabe 'A'
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
ret42 20 30 3 123 65
Die allgemeine Adressierung lautet [Basis + Index*Faktor + Verschiebung] mit Faktor 1, 2, 4 oder 8. Bei einem Zugriff auf Speicher muss die Größe klar sein: Mit einem Register ergibt sie sich aus dessen Breite (mov eax, [x] lädt 4 Byte), sonst schreibst du byte, word, dword oder qword.
Arrays durchlaufen
section .data
zahlen dq 5, 3, 9, 1, 7, 12, 4
anzahl equ 7
section .bss
puffer resb 32
section .text
global _start
_start:
; Summe und Maximum
xor rax, rax ; Summe
mov rbx, [zahlen] ; Maximum (erstes Element)
xor rcx, rcx ; Index
.schleife:
mov rdx, [zahlen + rcx*8]
add rax, rdx
cmp rdx, rbx
jle .weiter
mov rbx, rdx
.weiter:
inc rcx
cmp rcx, anzahl
jl .schleife
call ausgabe_zahl ; Summe
mov rax, rbx
call ausgabe_zahl ; Maximum
; Bubblesort
mov r8, anzahl - 1
.aussen:
xor rcx, rcx
.innen:
mov rax, [zahlen + rcx*8]
mov rdx, [zahlen + rcx*8 + 8]
cmp rax, rdx
jle .ok
mov [zahlen + rcx*8], rdx
mov [zahlen + rcx*8 + 8], rax
.ok:
inc rcx
cmp rcx, r8
jl .innen
dec r8
jnz .aussen
xor rcx, rcx
.ausgabe:
mov rax, [zahlen + rcx*8]
call ausgabe_zahl
inc rcx
cmp rcx, anzahl
jl .ausgabe
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
ret41 12 1 3 4 5 7 9 12
Zeichenketten
Eine Zeichenkette ist eine Folge von Bytes (ASCII-Codes). Hier die klassische Aufgabe: Länge bestimmen, Großschreibung, Umkehren:
section .data
text db "Hallo Assembler", 0
nl db 10
section .bss
puffer resb 32
kopie resb 64
section .text
global _start
_start:
; Länge bis zum Nullbyte
xor rcx, rcx
.laenge:
cmp byte [text + rcx], 0
je .laenge_fertig
inc rcx
jmp .laenge
.laenge_fertig:
mov r8, rcx ; Länge merken
mov rax, r8
call ausgabe_zahl
; Kopie in Großbuchstaben
xor rcx, rcx
.gross:
mov al, [text + rcx]
cmp al, 'a'
jb .behalten
cmp al, 'z'
ja .behalten
sub al, 32 ; 'a' (97) → 'A' (65)
.behalten:
mov [kopie + rcx], al
inc rcx
cmp rcx, r8
jb .gross
mov byte [kopie + r8], 10
mov rax, 1 ; write(1, kopie, länge+1)
mov rdi, 1
mov rsi, kopie
lea rdx, [r8 + 1]
syscall
; Rückwärts ausgeben
mov rcx, r8
.rueck:
dec rcx
mov rax, 1
mov rdi, 1
lea rsi, [text + rcx]
mov rdx, 1
push rcx
syscall
pop rcx
test rcx, rcx
jnz .rueck
mov rax, 1
mov rdi, 1
mov rsi, nl
mov rdx, 1
syscall
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
ret15 HALLO ASSEMBLER relbmessA ollaH
Es gibt auch String-Befehle (movsb, stosb, lodsb, scasb, cmpsb) mit dem Präfix rep, die mit rsi/rdi/rcx ganze Blöcke bearbeiten:
section .data
quelle db "Kopiere mich", 10
laenge equ $ - quelle
section .bss
ziel resb 32
section .text
global _start
_start:
mov rsi, quelle
mov rdi, ziel
mov rcx, laenge
cld ; Richtung vorwärts
rep movsb ; kopiert rcx Bytes von [rsi] nach [rdi]
mov rax, 1
mov rdi, 1
mov rsi, ziel
mov rdx, laenge
syscall
mov rdi, ziel ; Speicher mit 'x' füllen
mov al, 'x'
mov rcx, 5
rep stosb
mov byte [ziel + 5], 10
mov rax, 1
mov rdi, 1
mov rsi, ziel
mov rdx, 6
syscall
mov rax, 60
xor rdi, rdi
syscallKopiere mich xxxxx
Merke
[adresse]liest/schreibt Speicher,leaberechnet nur Adressen- Adressierung:
[Basis + Index*Faktor + Verschiebung] db/dw/dd/dqin.data,resb/resqin.bss- Arrays: Index mal Elementgröße; Strings: Bytes bis Nullbyte
rep movsb/stosbkopieren und füllen Blöcke
Aufgabe
Schreibe eine Routine, die eine Zeichenkette in Kleinbuchstaben umwandelt.