Assemblersprache - Arrays

Ein Array ist eine Sammlung von Daten desselben Typs, die zusammenhängend gespeichert sind. In Assembler ist ein Array ein zusammenhängender Speicherblock, und auf jedes Element wird über eine Basisadresse plus einen Offset zugegriffen.


Definition eines eindimensionalen Arrays

Beispiel

; Möglichkeiten zur Definition eines Arrays

section .data
    ; Methode 1: Elemente einzeln auflisten
    arr1 dd 10, 20, 30, 40, 50  ; Ein Array mit 5 Doppelwort-Elementen

    ; Methode 2: Mit dup initialisieren
    arr2 dd 10 dup(0)            ; 10 Doppelwörter, alle 0

    ; Methode 3: Byte-Array
    bytes db 1, 2, 3, 4, 5, 6   ; 6 Bytes

    ; Methode 4: Zeichenarray (Zeichenkette)
    chars db 'example', 0         ; 7 Bytes

    ; Array-Längenberechnung (zur Kompilierzeit)
    arr1_len equ ($ - arr1) / 4  ; Anzahl der Elemente in einem Doppelwort-Array
    arr2_len equ ($ - arr2) / 4
    bytes_len equ ($ - bytes)    ; Byte-Array, keine Division erforderlich

section .bss
    ; Uninitialisiertes Array
    buffer resd 100              ; Speicherplatz für 100 Doppelwörter reservieren

Zugriff auf Array-Elemente

Beim Zugriff auf Array-Elemente wird der AdressierungsmodusBasis + Index × Elementgrößeverwendet:

Beispiel

; Dateipfad: array_access.asm
; Lesen und Schreiben von Array-Elementen

section .data
    nums dd 100, 200, 300, 400, 500   ; 5 Elemente
    nums_len equ ($ - nums) / 4

section .text
    global _start

_start:
    ; Zugriff auf das 0. Element (Index 0)
    mov eax, [nums]              ; eax = 100

    ; Zugriff auf das 2. Element (Index 2)
    mov eax, [nums + 2 * 4]      ; eax = nums[2] = 300
    ; 2 * 4 = 8, also ein Offset von 8 Bytes von nums

    ; Verwenden Sie ein Register als Index
    mov esi, 3                   ; Index = 3
    mov eax, [nums + esi * 4]    ; eax = nums[3] = 400

    ; Array-Elemente ändern
    mov dword [nums + 4], 250    ; nums[1] = 250
    ; Das Array enthält nun: 100, 250, 300, 400, 500

    ; EBX als Basisregister verwenden
    mov ebx, nums                ; ebx = Array-Basisadresse
    mov eax, [ebx + 4 * 4]       ; eax = nums[4] = 500

    mov eax, 1
    mov ebx, 0
    int 0x80

Hinweis:[nums + esi * 4]Die Multiplikation mit 4 erfolgt, weil jedes Element 4 Bytes (Doppelwort) groß ist. Für ein Byte-Array (db) schreiben Sie es direkt als[arr + esi]; für ein Wort-Array (dw) schreiben Sie es als[arr + esi * 2]。


Array-Durchlauf

Beispiel

; Dateipfad: array_traverse.asm
; Durchlaufen des Arrays und Berechnen der Summe

section .data
    numbers dd 5, 10, 15, 20, 25, 30, 35, 40, 45, 50
    count equ ($ - numbers) / 4   ; Anzahl der Elemente

section .text
    global _start

_start:
    mov ecx, count                ; Schleifenzähler
    mov esi, 0                    ; Index (beginnend bei 0)
    mov eax, 0                    ; Akkumulierte Summe

sum_loop:
    add eax, [numbers + esi * 4]  ; Array-Elemente akkumulieren
    inc esi                       ; Index + 1
    loop sum_loop
    ; eax = 5+10+15+...+50 = 275

    ; Eine andere Durchlauftheorie: Verwendung eines Zeigers
    mov ecx, count
    mov ebx, numbers              ; ebx zeigt auf den Anfang des Arrays
    mov eax, 0                    ; Akkumulierte Summe

sum_loop2:
    add eax, [ebx]                ; Aktuelles Element akkumulieren
    add ebx, 4                    ; Zeiger auf das nächste Element bewegen
    loop sum_loop2
    ; eax = 275

    mov ebx, eax                  ; Exit-Code = akkumulierte Summe
    mov eax, 1
    int 0x80

Array-Suche

Beispiel

; Dateipfad: array_search.asm
; Nach einem bestimmten Wert im Array suchen

section .data
    data dd 12, 45, 67, 23, 89, 34, 56, 78, 90, 11
    data_len equ ($ - data) / 4
    target dd 23                   ; Der Wert, nach dem gesucht werden soll
    found_msg db 'Gefunden bei Index: ', 0
    found_len equ $ - found_msg
    notfound_msg db 'Nicht gefunden (Beispiel)', 0xA
    notfound_len equ $ - notfound_msg
    newline db 0xA

section .text
    global _start

_start:
    mov ecx, data_len             ; Schleifenzähler
    mov esi, 0                    ; Aktueller Index

search_loop:
    mov eax, [data + esi * 4]     ; Aktuelles Element laden
    cmp eax, [target]             ; Ob es dem Zielwert entspricht
    je  found                     ; Gefunden

    inc esi                       ; Index + 1
    loop search_loop

    ; Nicht gefunden
    mov eax, 4
    mov ebx, 1
    mov ecx, notfound_msg
    mov edx, notfound_len
    int 0x80
    jmp exit

found:
    ; Gefunden (esi ist der Index)
    mov eax, 4
    mov ebx, 1
    mov ecx, found_msg
    mov edx, found_len
    int 0x80

    ; Den Index in ein ASCII-Zeichen umwandeln und ausgeben
    add esi, '0'                  ; Einen einstelligen Index in ein Zeichen umwandeln
    push esi                      ; Zur temporären Speicherung auf den Stack legen
    mov eax, 4
    mov ebx, 1
    mov ecx, esp                  ; Stacktop-Adresse
    mov edx, 1
    int 0x80
    pop esi

    ; Eine neue Zeile ausgeben
    mov eax, 4
    mov ebx, 1
    mov ecx, newline
    mov edx, 1
    int 0x80

exit:
    mov eax, 1
    mov ebx, 0
    int 0x80

Zweidimensionales Array

Ein zweidimensionales Array wird zeilenweise in einen eindimensionalen Speicher im Arbeitsspeicher expandiert. Die Adressformel für den Zugriffarr[i][j]lautet:

地址 = 基址 + (i*列数 + j) * 元素大小

Beispiel

; Dateipfad: 2d_array.asm
= 10 (Zeile 3, Spalte 2)

section .data
   
    matrix dd 1,  2,  3,  4
           dd 5,  6,  7,  8
           dd 9, 10, 11, 12

    rows equ 3
    cols equ 4
    elem_size equ 4              ; DWORD = 4 Bytes

section .text
    global _start

_start:
    ; Auf Matrix zugreifen
    ; Adresse = matrix + (1*4 + 2) * 4 = matrix + 24

    mov eax, [matrix + (1 * cols + 2) * elem_size]
    ; eax = 7

    ; Dynamische Berechnung über Register (angenommen i=2, j=1)
    ; matrix
    mov esi, 2                   ; Zeile i = 2
    mov edi, 1                   ; Spalte j = 1

    mov eax, cols                ; Anzahl der Spalten
    mul esi                      ; eax = i * cols = 2*4 = 8
    add eax, edi                 ; eax = i*cols + j = 8+1 = 9
    ; eax = eax * elem_size
    ; Hinweis: Das Ergebnis von MUL ist in EAX, hier direkt verwenden
    mov eax, [matrix + eax * elem_size]
    ; eax = 10

    ; Alle Elemente eines 2D-Arrays durchlaufen
    mov ecx, rows * cols         ; Gesamtzahl der Elemente = 12
    mov esi, 0                   ; Index
    mov ebx, 0                   ; Aufummierte Summe

traverse:
    add ebx, [matrix + esi * elem_size]
    inc esi
    loop traverse
    ; ebx = 1+2+3+...+12 = 78

    mov eax, 1
    int 0x80

Vollständiges Beispiel für Blasensortierung

Beispiel

; Dateipfad: bubble_sort.asm
; Blasensortieralgorithmus

section .data
    array dd 64, 34, 25, 12, 22, 11, 90, 78
    array_len equ ($ - array) / 4

section .text
    global _start

_start:
    mov ecx, array_len            ; Äußere Schleife: n Mal
    dec ecx                       ; Die äußere Schleife benötigt nur n-1 Mal

outer_loop:
    push ecx                      ; Zähler der äußeren Schleife speichern

    mov esi, 0                    ; Index der inneren Schleife beginnt bei 0
    mov ecx, array_len - 1        ; Anzahl der Iterationen der inneren Schleife

inner_loop:
    mov eax, [array + esi * 4]    ; a[j]
    mov ebx, [array + esi * 4 + 4]  ; a[j+1]
    cmp eax, ebx                  ; a[j] > a[j+1] ?
    jle no_swap                   ; Nein, nicht tauschen

    ; Tausche a[j] und a[j+1]
    mov [array + esi * 4], ebx
    mov [array + esi * 4 + 4], eax

no_swap:
    inc esi
    loop inner_loop

    pop ecx
    loop outer_loop
    ; Array ist jetzt sortiert: 11, 12, 22, 25, 34, 64, 78, 90

    mov eax, 1
    mov ebx, 0
    int 0x80

Arrays in der Assembly-Sprache haben keine Bereichsprüfung (Boundary Checking). Der Zugriff auf einen Index außerhalb der Grenzen löst keinen Fehler aus; stattdessen werden stillschweigend Daten im benachbarten Speicher gelesen oder geschrieben, was zu schwer zu debuggenden Fehlern führen kann. Stellen Sie unbedingt selbst sicher, dass sich der Index innerhalb gültiger Grenzen befindet.

Weitere Erweiterungen