Assembler/Hello World

Aus Ringo's Wiki
Zur Navigation springen Zur Suche springen

Das erste lauffähige Programm (Hello World!)

Wie in jedem guten Tutorial ;) zum erlernen einer Programmiersprache gibt's ein obligatorisches "Hello World!"-Programm.

zuerst der Code, dann die Erläuterungen dazu:

01 format ELF64 executable at 0000000100000000h	; put image over 32-bit limit
02
03 segment readable executable
04
05 entry $
06
07     mov edx, msg_size	; CPU zero extends 32-bit operation to 64-bit
08				; we can use less bytes than in case mov rdx,...
09     lea rsi, [msg]
10     mov edi, 1		; STDOUT
11     mov eax, 1		; sys_write
12     syscall
13
14     xor edi, edi		; exit code 0
15     mov eax, 60		; sys_exit
16     syscall
17
18 segment readable writeable
19
20 msg db 'Hello World! 64-Bit-Version', 0xA
21 msg_size = $ - msg

In der 1. Zeile wird angegeben, dass diese Datei eine Ausführbare 64-Bit ELF64 Datei sein soll.
In der 3. Zeile wird ein lesbarer (readable) und ausführbarer (executable) Bereich begonnen.
In der 5. Zeile wird der Einstiegspunkt des ausführbaren Bereichs gekennzeichnet.

Ab der 7. Zeile wird es interessant! Hier wird die Länge der Zeichenkette, die wir ausgeben wollen in das CPU-Register "edx" kopiert (gemoved)
Die Daten dafür beginnen ab Zeile 18 mit "segment readable writeable"
In Zeile 20 wird der String, den wir ausgeben wollen als DatenBytes geschrieben. Wie man sehen kann, wird dem Eigentlichen String noch ein 0xA angehangen, dies ist das Zeichen für einen Zeilenumbruch unter Linux.
In anderen Programmiersprachen wie C oder PHP realisiert man das normalerweise mit einem \n, was auch nichts anderes ist, als das 10. Symbol in der ASCII-Tabelle. Man könnte anstelle des 0xA auch 0x0A oder 10 schreiben.
Die Adresse des Strings wird in msg gespeichert! Diese wird auch gleich in Zeile 21 verwendet, um die String-Länge zu berechnen! $ ist dabei die aktuelle Adresse und davon wird die Adresse von msg abgezogen, somit hat man die String-Länge, die in msg_size gespeichert wird und in Zeile 7 verwendet wird.

In der 9. Zeile wird die Speicheradresse von msg ins rsi-Register geladen.
In der 10. und 11. Zeile wird festgelegt, dass die Ausgabe nach stdout geschrieben werden soll.
In der 12. Zeile wird die Ausgabe ausgeführt.

In der 14. und 15. Zeile wird der exit_code auf 0 gesetzt.
In der 16. Zeile wird das Programm beendet.

Jedes Programm muss Ordnungsgemäß wie in Zeile 14 bis 16 beendet werden, wobei der exit_code natürlich angepasst werden kann, um bestimmte Fehlerzustände zurückzugeben.
Beendet man Ein Programm nicht richtig, so arbeitet die CPU einfach an der nächsten Speicherstelle weiter, da man aber nicht weiß, was nach dem normalen Programm kommt, kann alles mögliche ausgeführt werden, was wiederum eine Hintertür einbaut.

Kommentare werden in Assembler mit einem Semikolon (;) eingeleitet und enden am Ende der Zeile.