Assemblersprache - Grundlegende Syntax

Dieses Kapitel stellt die Grundstruktur, Syntaxregeln und Schreibkonventionen von NASM-Assemblerprogrammen vor und hilft Ihnen, das Grundgerüst von Assemblercode zu verstehen.


Grundstruktur eines Assemblerprogramms

Ein vollständiges NASM-Assemblerprogramm besteht normalerweise aus den folgenden Teilen:

Beispiel

; Dateipfad: structure.asm
; Beispiel für eine grundlegende NASM-Programmstruktur

section .data                       ; Datenabschnitt: speichert initialisierte Daten
    ; Definieren Sie hier Variablen und Konstanten
    msg db 'Hello, EXAMPLE!', 0xA
    len equ $ - msg

section .bss                        ; BSS-Abschnitt: speichert uninitialisierte Daten
    ; Reservieren Sie hier Speicherplatz
    buffer resb 64                  ; Reserviere einen 64-Byte-Puffer

section .text                       ; Codeabschnitt: speichert ausführbare Anweisungen
    global _start

_start:
    ; Schreiben Sie hier die Programmlogik
    mov eax, 4
    mov ebx, 1
    mov ecx, msg
    mov edx, len
    int 0x80

    mov eax, 1
    mov ebx, 0
    int 0x80
BereichZweckEigenschaften
.dataSpeichert initialisierte globale Variablen und KonstantenGröße und Inhalt werden zur Kompilierungszeit bestimmt, im ausführbaren Datei gespeichert
.bssSpeichert uninitialisierte globale VariablenSpeicherplatz wird erst zur Laufzeit zugewiesen, belegt keine Größe der ausführbaren Datei
.textSpeichert ausführbare MaschinenbefehleSchreibgeschützt, enthält den gesamten Logikcode des Programms

Mindestens.textAbschnitte sind erforderlich, um ein gültiges Assemblerprogramm zu bilden. Wenn keine Daten vorhanden sind, kann der.dataund.bss-Abschnitt weggelassen werden.


Format der Assembleranweisung

Das allgemeine Format jeder Assembleranweisung ist:

[标签:]   指令助记符   [操作数1 [, 操作数2 [, 操作数3]]]   [; 注释]

Erklärung der einzelnen Teile:

TeilErforderlich?Beschreibung
LabelOptionalEin symbolischer Name, der eine Speicheradresse darstellt, endend mit einem Doppelpunkt
BefehlsmnemonicErforderlichWie mov, add, sub usw., teilt der CPU mit, was zu tun ist
OperandOptional (einige Befehle haben keinen Operanden)Das vom Befehl bearbeitete Datenobjekt kann ein Register, eine Speicheradresse oder ein unmittelbarer Wert sein
KommentarOptionalBeginnt mit einem Semikolon und geht bis zum Ende der Zeile

Beispiel

; Beispiele für verschiedene Anweisungsformate

; Nur Befehl, kein Operand
ret                     ; Rückkehr aus Subroutine

; Befehl + einzelner Operand
push eax                ; Den Wert von eax auf den Stapel legen
inc ecx                 ; Addiere 1 zu ecx

; Befehl + zwei Operanden (am häufigsten)
mov eax, 42             ; Kopiere 42 in das eax-Register
add ebx, ecx            ; ebx = ebx + ecx

; Mit einer Marke (Label)
loop_start:             ; Label: markiert den Beginn der Schleife
    dec ecx             ; Subtrahiere 1 von ecx
    jnz loop_start      ; Wenn ecx nicht 0 ist, springe zurück zu loop_start

Kommentarkonventionen

NASM verwendet dasSemikolon (;), um Kommentare zu kennzeichnen; Inhalte ab dem Semikolon bis zum Ende der Zeile werden vom Assembler ignoriert.

Beispiel

; Ganzzeilenkommentar: erklärt den Zweck des folgenden Codeblocks
; Berechne die Summe zweier Zahlen und gib das Ergebnis aus

mov eax, 10             ; Inline-Kommentar: schreibe 10 in eax
add eax, 20             ; Inline-Kommentar: addiere 20 zu eax, jetzt ist eax = 30

Kommentare sind im Assemblercode äußerst wichtig. Ohne Kommentare versteht selbst der Autor den Assemblercode nach ein paar Wochen möglicherweise nicht mehr. Machen Sie es sich zur Gewohnheit, für jeden Befehl einen Kommentar zu schreiben.


Regeln für die Benennung von Bezeichnern

Bezeichner (Labels, Variablennamen, Konstantennamen usw.) müssen den folgenden Regeln folgen:

RegelBeschreibung
Zulässige ZeichenBuchstaben, Ziffern, Unterstrich _, Punkt ., Fragezeichen ?, @, $, # usw.
StartzeichenMuss mit einem Buchstaben, Unterstrich, Punkt oder Fragezeichen beginnen; darf nicht mit einer Ziffer beginnen.
Groß-/KleinschreibungStandardmäßig groß-/kleinschreibungssensitiv (kann über Kompilierungsoptionen geändert werden)
Reservierte WörterDürfen nicht denselben Namen haben wie Befehlsmneonics, Registernamen oder NASM-Schlüsselwörter.

Beispiel

; Gültige Bezeichner
my_variable:            ; Beginnt mit einem Buchstaben + Unterstrich
.loop_start:            ; Beginnt mit einem Punkt (lokales Label)
?error_handler:         ; Beginnt mit einem Fragezeichen
counter2:               ; Buchstabe + Ziffer

; Ungültige Bezeichner (nur zur Referenz, nicht verwenden)
; 1st_value: ; Fehler: darf nicht mit einer Ziffer beginnen
; mov: ; Fehler: mov ist ein reserviertes Wort
; my-variable: ; Fehler: Bindestrich ist kein gültiges Zeichen

Pseudo-Anweisungen (Direktiven)

Direktivensind Befehle für den Assembler, keine Befehle für die CPU; sie steuern den Assemblierungsprozess und definieren Datenstrukturen.

DirektivenZweckBeispiel
dbByte definieren (1 Byte)byte_val db 0x55
dwWord definieren (2 Bytes)word_val dw 0x1234
ddDouble Word definieren (4 Bytes)dword_val dd 0x12345678
equKonstante definierenMAX_SIZE equ 256
resbByte-Speicher reservierenbuffer resb 128
reswWord-Speicher reservierenwbuf resw 64
resdDouble-Word-Speicher reservierendbuf resd 32
%defineMakrodefinierte Konstante%define COUNT 10

Schreibkonventionen

NASM unterscheidet bei Marken und Bezeichnern standardmäßig zwischen Groß- und Kleinschreibung.:

Beispiel

; Beispiel für Groß-/Kleinschreibungsempfindlichkeit

section .data
    msg db 'EXAMPLE', 0       ; Variable msg definieren

section .text
    global _start

_start:
    mov eax, MSG             ; Fehler: MSG und msg sind unterschiedlich (außer der Modus für Groß-/Kleinschreibung ist deaktiviert)
    mov eax, msg             ; Korrekt: msg stimmt genau mit der Definition überein

    MOV EAX, 42              ; Syntaktisch korrekt: Befehlsschnitte sind unabhängig von Groß- und Kleinschreibung
    mov eax, 42              ; Empfohlener Stil: Kleinbuchstaben für bessere Lesbarkeit verwenden

Befehlsschnitte und Registernamen sind unabhängig von Groß- und Kleinschreibung (MOV、Mov、movgleicher Effekt), aber der empfohlene Stil ist durchgehend in Kleinbuchstaben.


Numerische Darstellung

NASM unterstützt die numerische Darstellung in mehreren Basen:

Beispiel

; Darstellung verschiedener Basen in NASM

mov eax, 42             ; Dezimal: Zahl direkt schreiben
mov eax, 0x2A           ; Hexadezimal: 0x-Präfix (empfohlener Stil)
mov eax, 2Ah            ; Hexadezimal: h-Suffix
mov eax, 0o52           ; Oktal: 0o-Präfix
mov eax, 52o            ; Oktal: o-Suffix
mov eax, 101010b        ; Binär: b-Suffix
mov eax, 0b101010       ; Binär: 0b-Präfix

Empfohlen:0xPräfix für Hexadezimal verwenden (z. B.0x2A), damit es weniger wahrscheinlich mit Marken verwechselt wird.


Ein vollständiges Syntaxbeispiel

Das folgende Programm verwendet die obigen Syntaxelemente umfassend, um die Summe von 1 bis 10 zu berechnen und auszugeben:

Beispiel

; Dateipfad: sum.asm
; 1+2+...+10 berechnen und das Ergebniszeichen ausgeben

section .data
    result db 0                 ; Berechnungsergebnis speichern (1 Byte)
    newline db 0xA              ; Zeilenumbruchzeichen

section .text
    global _start

_start:
    ; Register und Variablen initialisieren
    mov ecx, 10                 ; Schleifenzähler: von 10 herunterzählen
    mov eax, 0                  ; eax speichert die akkumulierte Summe, anfangs 0

sum_loop:                       ; Schleifenstartmarke
    add eax, ecx                ; eax = eax + ecx
    dec ecx                     ; ecx um 1 dekrementieren
    jnz sum_loop                ; Wenn ecx != 0, Schleife fortsetzen

    ; Zu diesem Zeitpunkt ist eax = 55 (10+9+...+1)
    add eax, '0'                ; Zahl in ASCII-Zeichen umwandeln ('0'=48, 55+48=103='g', falsch)
                                ; Die eigentliche Demonstration erfordert eine komplexere Konvertierung, siehe spätere Kapitel

    ; Hier nur Ergebnisausgabe (vereinfachte Demonstration)
    mov [result], al            ; Akkumuliertes Ergebnis in result speichern

    ; Programm beenden
    mov eax, 1
    mov ebx, 0
    int 0x80

Hinweis: Im obigen Beispiel ist das direkte Hinzufügen von '0' nur korrekt, wenn die Zahl im Bereich 0-9 liegt. Das Konvertieren von Zahlen mit zwei oder mehr Ziffern wird in späteren Kapiteln detailliert erläutert.

Weitere Erweiterungen