Assemblersprache - Variablen
Variablen sind die Grundeinheiten zum Speichern von Daten in einem Programm. Das Definieren und Verwenden von Variablen in der Assemblersprache ist näher an der zugrunde liegenden Hardware als in höheren Programmiersprachen; Sie müssen die Größe, den Typ und das Speicherlayout von Variablen direkt steuern.
Konzept der Variablen in Assembler
In der Assemblersprache isteine Variableim Wesentlichen ein benannter Speicherort im Speicher.
Im Gegensatz zu höheren Programmiersprachen haben Assemblervariablen keine automatische Typprüfung – ein Label ist nur ein Alias für eine Speicheradresse, und Sie können es in jeder beliebigen Größe lesen oder schreiben.
NASM stellt drei Sektionen zur Verfügung, um verschiedene Arten von Variablen zu speichern:.data(initialisiert),.bss(nicht initialisiert) und.rodata(schreibgeschützt).
Definieren initialisierter Variablen in der Sektion .data
Verwenden Sie die Direktiven DB, DW, DD, DQ, DT, um Variablen verschiedener Größen zu definieren:
| Direktive | Datenmenge | Bedeutung | Beispiel |
|---|---|---|---|
| DB | 1 Byte | Byte definieren | flag db 1 |
| DW | 2 Byte | Wort (Word) definieren | count dw 1000 |
| DD | 4 Byte | Doppelwort (Doubleword) definieren | price dd 9999 |
| DQ | 8 Bytes | Quadwort (Quadword) definieren | big_val dq 0x1234567890ABCDEF |
| DT | 10 Bytes | Zehn Bytes definieren | ext_val dt 3.14 |
Beispiel
; Demonstriert das Definieren verschiedener Variablen in der .data-Sektion
section .data
; Byte-Variable
status db 1 ; 1 Byte, Wert 1
grade db 'A' ; 1 Byte, Zeichen 'A' = 0x41
; Wort-Variable (2 Bytes)
year dw 2026 ; 2 Bytes, Wert 2026
; Doppelwort-Variable (4 Bytes)
salary dd 50000 ; 4 Bytes, Wert 50000
; Mehrbyte-Sequenz
msg db 'Hello, example!', 0 ; Nullterminierte Zeichenkette (C-Stil)
hex_bytes db 0x55, 0xAA, 0x00, 0xFF ; Hexadezimale Byte-Sequenz
; Wiederholter Wert
stars db 10 dup('*') ; 10 Sternchen-Zeichen
; Mehrere Variablen mit Namen
x dd 10
y dd 20
z dd 30
section .text
global _start
_start:
; Variablenwerte in Register einlesen
mov al, [status] ; al = 1 (1 Byte lesen)
mov ax, [year] ; ax = 2026 (2 Bytes lesen)
mov eax, [salary] ; eax = 50000 (4 Bytes lesen)
; Variablenwerte ändern
mov byte [status], 0 ; status = 0
mov dword [x], 100 ; x = 100
mov eax, 1
mov ebx, 0
int 0x80
Verwenden Sie
[variable name]Stellen Sie beim Zugriff auf eine Variable sicher, dass die Anzahl der gelesenen/geschriebenen Bytes mit der für die Variable definierten Größe übereinstimmt. Verwenden Siemov al, [status]um 1 Byte zu lesen, verwenden Siemov eax, [salary]um 4 Bytes zu lesen. NASM überprüft, ob die Größen der Operanden übereinstimmen.
Reservieren von nicht initialisiertem Speicherplatz in der Sektion .bss
Verwenden Sie Direktiven wie RESB, RESW, RESD, um Speicherplatz zu reservieren (ohne zu initialisieren):
| Direktive | Reservierte Größe | Beispiel |
|---|---|---|
| RESB | Byte | buffer resb 256 |
| RESW | Wort (2 Bytes) | wbuf resw 100 |
| RESD | Doppelwort (4 Bytes) | dbuf resd 50 |
| RESQ | Quadwort (8 Bytes) | qbuf resq 25 |
Beispiel
; Demonstriert das Reservieren von Speicherplatz in der .bss-Sektion
section .bss
input_buf resb 128 ; Einen 128-Byte-Eingabepuffer reservieren
numbers resd 100 ; 100 Doppelwörter (400 Bytes) reservieren
temp resb 1 ; Eine temporäre 1-Byte-Variable reservieren
section .data
prompt db 'Enter a number: '
prompt_len equ $ - prompt
section .text
global _start
_start:
; Eingabeaufforderung
mov eax, 4
mov ebx, 1
mov ecx, prompt
mov edx, prompt_len
int 0x80
; Eingabe in den Puffer in der .bss-Sektion einlesen
mov eax, 3
mov ebx, 0
mov ecx, input_buf ; Den in der .bss-Sektion reservierten Speicherplatz verwenden
mov edx, 128
int 0x80
; Daten in das Zahlen-Array füllen
mov dword [numbers], 42 ; numbers[0] = 42
mov dword [numbers + 4], 100 ; numbers[1] = 100
mov eax, 1
mov ebx, 0
int 0x80
Speicherlayout von Bytes, Wörtern und Doppelwörtern
x86 verwendetLittle-Endian (Little Endian)– das niedrigstwertige Byte wird an der niedrigsten Adresse gespeichert.
Wenn Sie beispielsweisevalue dd 0x12345678definieren, sieht das Speicherlayout wie folgt aus:
地址 :[value] [value+1] [value+2] [value+3] 内容 :0x78 0x56 0x34 0x12
Beispiel
; Demonstration der Little-Endian-Speicherung
section .data
value dd 0x12345678 ; Doppelwort, 4 Bytes
section .text
global _start
_start:
; Lesen derselben Variable in verschiedenen Größen
mov eax, [value] ; 4 Bytes lesen: eax = 0x12345678
mov ax, [value] ; 2 Bytes lesen: ax = 0x5678 (untere 2 Bytes)
mov al, [value] ; 1 Byte lesen: al = 0x78 (niedrigstes Byte)
; Little-Endian überprüfen: niedrigere Adressen speichern niederwertigere Bytes
mov al, [value] ; al = 0x78
mov bl, [value + 1] ; bl = 0x56
mov cl, [value + 2] ; cl = 0x34
mov dl, [value + 3] ; dl = 0x12
mov eax, 1
mov ebx, 0
int 0x80
Initialisierung und Zugriff auf Variablen
In der Assemblersprache folgen Variablemationen dem Dreistufenmuster "Laden-Verarbeiten-Speichern":
Beispiel
; Demonstration des Dreistufenmusters von Variablenoperationen
section .data
a dd 100
b dd 200
result dd 0
section .text
global _start
_start:
; result = a + b
; Schritt 1: Laden
mov eax, [a] ; Lade a in eax
; Schritt 2: Verarbeiten
add eax, [b] ; eax = eax + b
; Schritt 3: Speichern
mov [result], eax ; Speichere das Ergebnis in result
; result = a * 2 - b
mov eax, [a]
imul eax, 2 ; eax = a * 2
sub eax, [b] ; eax = eax - b
mov [result], eax
mov eax, 1
mov ebx, 0
int 0x80
Assembler unterstützt
mov [result], [a] + [b]diese High-Level-Syntax nicht. Der x86-mov-Befehl kann nicht zwei Speicheroperanden gleichzeitig verwenden; er muss über ein Register als Vermittler laufen.
Variablengrößen-Operatoren
Wenn der Assembler die Operandengröße nicht ableiten kann, muss sie explizit angegeben werden:
Beispiel
section .data
var dd 0
section .text
global _start
_start:
; Größenoperatoren: byte, word, dword, qword
mov byte [var], 1 ; Schreibe 1 Byte
mov word [var], 1000 ; Schreibe 2 Bytes
mov dword [var], 999999 ; Schreibe 4 Bytes
; Wenn die Zielgröße klar ist (durch das Register bestimmt), kann sie weggelassen werden
mov al, [var] ; al ist 1 Byte, wird automatisch als byte gelesen
mov ax, [var] ; ax ist 2 Bytes, wird automatisch als word gelesen
mov eax, [var] ; eax ist 4 Bytes, wird automatisch als dword gelesen
; Die folgende Zeile führt jedoch zu einem Fehler (Größe ist mehrdeutig):
; mov [var], 1 ; Fehler! 1 könnte byte/word/dword sein
; Sie muss wie folgt geschrieben werden:
mov dword [var], 1 ; Explizite Angabe von 4 Bytes
mov eax, 1
mov ebx, 0
int 0x80