Das erste Programm "Hello World": Unterschied zwischen den Versionen

Aus C und Assembler mit Raspberry
KKeine Bearbeitungszusammenfassung
KKeine Bearbeitungszusammenfassung
 
(4 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 5: Zeile 5:


<syntaxhighlight lang="asm">
<syntaxhighlight lang="asm">
.global _start        // Definition der Einsprungadresse als GLOBAL, also der Startpunkt des Programms
.globl _start        // Definition der Einsprungadresse als GLOBAL, also der Startpunkt des Programms


_start:              // Label, das den Start des Programms markiert
_start:              // Label, das den Start des Programms markiert
Zeile 124: Zeile 124:
* Labels (_start und helloworld) sind Markierungen, die bestimmte Stellen im Code benennen.
* Labels (_start und helloworld) sind Markierungen, die bestimmte Stellen im Code benennen.
* Systemaufrufe (wie svc 0) sind spezielle Befehle, die dem Betriebssystem sagen, dass es etwas für unser Programm tun soll - wie auf den Bildschirm schreiben oder das Programm beenden.
* Systemaufrufe (wie svc 0) sind spezielle Befehle, die dem Betriebssystem sagen, dass es etwas für unser Programm tun soll - wie auf den Bildschirm schreiben oder das Programm beenden.
== Vorstellung der ARM64-Register (x0 - x30, SP, PC) ==
== Unterschiede zwischen allgemeinen und speziellen Registern ==
== Speicherorganisation und -adressierung ==

Aktuelle Version vom 1. Dezember 2024, 16:15 Uhr

Das erste Programm

In der Programmierung ist es traditionell, mit einem einfachen Programm zu beginnen, das "Hello World" auf dem Bildschirm ausgibt. In Assembler für ARM64 können wir dies auch tun.

Hier ist der vollständige Code und eine Erklärung, was jeder Abschnitt macht.

.globl _start        // Definition der Einsprungadresse als GLOBAL, also der Startpunkt des Programms

_start:               // Label, das den Start des Programms markiert
    mov x0, #1        // Setze das Register x0 auf 1, was StdOutput (Standardausgabe, wie der Bildschirm) bedeutet
    ldr x1, =helloworld // Lade die Adresse des Strings "helloworld" in das Register x1
    mov x2, #13       // Setze das Register x2 auf 13, die Länge des Strings "Hello World!\n"
    mov x8, #64       // Systemcall für Output (Schreiben auf den Bildschirm)
    svc 0             // Führe den Systemcall aus
    mov x0, #0        // Setze das Register x0 auf 0, was "keine Fehler" bedeutet
    mov x8, #93       // Systemcall für Exit (Programm beenden)
    svc 0             // Führe den Systemcall aus

.data                 // Definition des Datenbereichs
helloworld:           // Label für den String, der angezeigt werden soll
    .ascii "Hello World!\n" // Der String selbst, der ausgegeben wird

Schritt-für-Schritt-Erklärung

Globaler Startpunkt

.global _start

Dies definiert _start als global, sodass es vom Betriebssystem als der Startpunkt des Programms erkannt wird.

Programmstart

_start:

Dieses Label (_start:) markiert den Beginn des Programms. Bei Programmausführung beginnt der Prozessor hier.

Ausgabe auf Standardausgabe vorbereiten

mov x0, #1

Der Inhalt des Registers x0 wird auf 1 gesetzt, was den Standardausgabegerät (meistens der Bildschirm) symbolisiert.

Adresse des Strings in ein Register laden

ldr x1, =helloworld

Der Speicherort (die Adresse) des “helloworld”-Strings wird in das Register x1 geladen.

Die Länge des Strings spezifizieren

mov x2, #13

Der Wert 13 wird in das Register x2 geladen, was die Länge des Strings "Hello World!\n" (12 Zeichen + neues Zeilenzeichen) darstellt.

Systemcall für Output (Schreiben) definieren

mov x8, #64

Der Wert 64 wird in das Register x8 geladen. Dies ist der Befehlscode für den Systemcall write (zum Schreiben auf den Bildschirm).

Systemcall ausführen

svc 0

Dies führt den Systemcall aus und schreibt den String auf den Bildschirm.

Erfolg melden und Programm beenden

mov x0, #0

Setzt x0 auf 0, was "keine Fehler" bedeutet.

Systemcall für Exit (Beenden) setzen

mov x8, #93

Der Wert 93 wird in x8 geladen, was der Befehlscode für exit (Programm beenden) ist.

Systemcall ausführen

svc 0

Führt den Systemcall aus, um das Programm zu beenden.

Datenbereich

.data

Dies markiert den Beginn des Datenbereichs, wo unsere Daten (der String) gespeichert werden.

String definieren

helloworld: 
   .ascii "Hello World!\n"

Hier wird der String (Hello World!\n) definiert und die Adresse als helloworld markiert. \n steht für einen Zeilenumbruch.

Kompilieren und Ausführen

Um das Programm zum Laufen zu bringen, sind nun folgende Schritte nötig:

Kompilieren

as -o HelloWorld.o HelloWorld.s

Dies übersetzt den Assembler-Code (HelloWorld.s) in ein Objektfile (HelloWorld.o).

Linken

ld -o HelloWorld HelloWorld.o

Dies verbindet das Objektfile und erstellt ein ausführbares Programm namens HelloWorld.

Ausführen

./HelloWorld

Dies führt das Programm aus und sollte "Hello World!" auf dem Bildschirm ausgeben.

Erklärung in einfachen Worten

Wir gehen später nochmal auf alles ein und versuchen es spezifischer zu erklären.

  • mov, ldr, und svc sind Befehle, die dem Computer sagen, was er tun soll, wie das Bewegen von Daten oder das Ausführen von Systembefehlen.
  • Register (x0, x1, x2, x8) sind wie kleine Speicherplätze im Prozessor, die Daten zwischenspeichern.
  • Labels (_start und helloworld) sind Markierungen, die bestimmte Stellen im Code benennen.
  • Systemaufrufe (wie svc 0) sind spezielle Befehle, die dem Betriebssystem sagen, dass es etwas für unser Programm tun soll - wie auf den Bildschirm schreiben oder das Programm beenden.