Assemblersprache - Konstanten
Konstanten sind zur Kompilierzeit festgelegte Werte und können während der Programmausführung nicht geändert werden. Die Verwendung von Konstanten in Assembler macht den Code lesbarer und wartbarer.
Was sind Konstanten in Assembler?
In NASM sind KonstantenPseudobefehledefinierte Symbole. Der Assembler ersetzt alle Konstantenreferenzen zur Kompilierzeit durch tatsächliche Werte.
Im Gegensatz zu Variablen belegen Konstanten keinen Speicher im Datenbereich; sie werdenzur Kompilierzeitersetzt, was äquivalent zu `#define` in C ist.#define。
EQU – Konstante gleichsetzen
EQUDies ist die gängigste Art, Konstanten zu definieren; einmal definiert, kann sie nicht neu definiert werden:
Beispiel
; Numerische Konstanten
MAX_SIZE equ 256 ; Maximale Puffergröße
DEFAULT_PORT equ 8080 ; Standard-Portnummer
TRUE equ 1 ; Wahr
FALSE equ 0 ; Falsch
; Zeichenkonstanten
LF equ 0xA ; Neue Zeile
CR equ 0xD ; Wagenrücklauf
NULL equ 0 ; Null-Zeichen
; Ausdruckskonstanten
ARRAY_SIZE equ 100 * 4 ; Anzahl der Bytes für 100 Doppelwörter
BUFFER_SIZE equ MAX_SIZE * 2 ; Referenziert eine andere Konstante
TOTAL equ 10 + 20 + 30 ; Berechnungsergebnis
section .data
; Verwendung von Konstanten
buffer db MAX_SIZE dup(0) ; Definiere einen Puffer von MAX_SIZE Bytes
section .text
global _start
_start:
mov eax, MAX_SIZE ; eax = 256
mov ebx, BUFFER_SIZE ; ebx = 512
mov ecx, ARRAY_SIZE ; ecx = 400
mov eax, 1
mov ebx, 0
int 0x80
EQUMit EQU definierte Konstanten können im Programm nicht geändert und nicht neu definiert werden. Wenn Sie Konstanten benötigen, die neu definiert werden können (wie Makrovariablen), verwenden Sie%define。
%define – Makro-definierte Konstante
%defineSie ist flexibler als EQU, unterstützt Neubefehle und Bereichssteuerung (Scoping):
Beispiel
%define VERSION 1 ; Definiere Versionsnummer
%define APP_NAME 'example' ; Definiere Anwendungsnamen
; Konstanten definiert mit %define
mov eax, VERSION ; eax = 1
; Kann neu definiert werden (EQU erlaubt dies nicht)
%define VERSION 2 ; Versionsupgrade
mov eax, VERSION ; Jetzt eax = 2
; %undef hebt die Definition auf
%undef VERSION ; VERSION ist nicht mehr gültig
; mov eax, VERSION ; Fehler: VERSION ist nicht definiert
; %define kann mehrzeilige Makros definieren (mit Klammern)
%define sum(a, b) (a + b)
mov eax, sum(10, 20) ; mov eax, (10+20) -> eax = 30
| Funktionen | EQU | %define |
|---|---|---|
| Kann neu definiert werden | nein | Ja |
| Kann undefiniert werden | nein | Ja (%undef) |
| Unterstützt Parameter | nein | Ja (Makrofunktionen) |
| Anwendungsfälle | Wahre Konstanten (unveränderliche Werte) | Variable Konfiguration, Makrosubstitution |
%assign – Zuweisbare Konstante
%assignWird verwendet, um numerische Konstanten zu definieren, die zur Kompilierzeit mehrfach geändert werden können:
Beispiel
%assign counter 0 ; Anfänglich 0
section .data
; Wird mit %rep wiederholten Blöcken verwendet
; Generiere table_0, table_1, ..., table_9
%rep 10
db counter ; Verwende den aktuellen Zählerwert
%assign counter counter + 1
%endrep
Praktische Anwendung von Konstanten in Programmen
Beispiel
; Konsequente Verwendung von Konstanten zur Verbesserung der Lesbarkeit des Codes
; Systemaufruf-Nummernkonstanten
SYS_EXIT equ 1
SYS_FORK equ 2
SYS_READ equ 3
SYS_WRITE equ 4
SYS_OPEN equ 5
SYS_CLOSE equ 6
; Dateideskriptorkonstanten
STDIN equ 0
STDOUT equ 1
STDERR equ 2
; Programmkonstanten
MAX_INPUT equ 256
EXIT_SUCCESS equ 0
EXIT_FAILURE equ 1
section .data
msg db 'Hello, EXAMPLE!', 0xA
msg_len equ $ - msg
section .bss
buffer resb MAX_INPUT ; Verwende eine Konstante, um die Puffergröße zu definieren
section .text
global _start
_start:
; Die Verwendung von Konstantennamen anstelle von Zahlen macht die Codeabsicht auf den ersten Blick klar
mov eax, SYS_WRITE ; Klar: Dies ist ein Schreibvorgang
mov ebx, STDOUT ; Klar: Ausgabe auf dem Bildschirm
mov ecx, msg
mov edx, msg_len
int 0x80
mov eax, SYS_EXIT ; Klar: Programm beenden
mov ebx, EXIT_SUCCESS ; Klar: normaler Exit
int 0x80
Die Verwendung von Konstantennamen anstelle von „magischen Zahlen“ ist eine gute Gewohnheit. Drei Monate später,
mov eax, SYS_WRITEVergleichenmov eax, 4ist es einfacher zu verstehen.
Zeichenfolge-Konstanten
NASM unterstützt mehrere Möglichkeiten, Zeichenfolge-Konstanten zu definieren:
Beispiel
section .data
; Direkte Definition (Länge kann mit EQU ausgedrückt werden)
s1 db 'hello', 0
s1_len equ $ - s1
; Mit Escape-Zeichen
s2 db 'Line1', 0xA, 'Line2', 0 ; 0xA ist das Zeilenumbruchzeichen
; Backticks verwenden, um Escape-Zeichen im C-Stil zu unterstützen
s3 db `hello\nworld\n`, 0 ; \n wird automatisch durch 0xA ersetzt
; Mehrzeilige Zeichenfolge
s4 db 'first line', 0xA
db 'second line', 0xA
db 'third line', 0
Weitere ErweiterungenDie Backtick-Zeichenfolgen von NASM unterstützen
\n(Zeilenumbruch),\t(Tabulator),\\(Backslash),\'(einfaches Anführungszeichen) und andere Standard-C-Escape-Sequenzen.