"Hello World" in Assembler unter MS-DOS (16 bit, i386er)

Beispiel:

Nachfolgend ein "Hello World" Programm in Assembler unter MS-DOS:

data	segment				; Deklaration: Bereich Variablen

txt	db	"Hello World",13,10,"$"  ; Text incl. Zeilenumbruch (= CR+LF, = ASCII 13+10), Textende = $

data	ends

code	segment				; Deklaration: Bereich Quellcode
	assume cs:code,ds:data		; Startpunkte für die 2 Bereiche definieren
	
_start:  				; 1. Label = Start-Label (Name ist egal)
	mov  ax,data			; Data Segment Register initialisieren
	mov  ds,ax			; Data Segment Register initialisieren

	mov  dx,OFFSET txt		; 1. Parameter, Textvariable
	mov  ah,09h			; Systemaufruf Nr. 9 = sys_write (Systemausgabe)
	int  21h			; DOS-Kernel aufrufen mit obigen Parametern

	mov  ah,4Ch			; Systemaufruf Nr. 4C = sys_exit (Programmende)
	int  21h			; DOS-Kernel aufrufen mit obigen Parametern

code    ends				; Ende des Codes markieren
	end  _start			; Ende des Start Label markieren

Erklärung:

Es folgt eine kurze Einführung, wie dieser Code zu lesen ist:

Der Programmcode unterteilt sich in 2 Sektionen. Unterhalb von 'data segment' befinden sich die 1 Variable (txt), die später im Programm verwendet wird. Unterhalb von 'code segment' steht der Programmcode, der ausgeführt werden soll. Dieser beginnt direkt im Anschluss daran. Zu Beginn werden verschiedene Register initialisiert und danach wird das eigentliche Programm definiert.

Das Programm verwendet ansich nur 2 Assembler-Befehle (mov und int).

'mov': kommt vom englischen 'moven' = bewegen. Dieser Befehl schreibt einen Wert in ein Register der CPU, sprich in eine der Speicherstellen, mit denen die CPU intern arbeitet und die daher sehr schnell sind. Wir verwenden später beim Compilieren das Tool 'MASM'. Dieser Compiler verwendet die Intel Notation, bei welcher zuerst angegeben wird WOHIN geschrieben werden soll (= der Name des Registers) und dann WAS dorthin geschrieben werden soll, sprich der zu verwendende Wert. Ein 'mov ah,09' schreibt also den Wert 9 in das AX Register, bzw. in den oberen Teil davon (high, AH).

'int' kommt vom englischen 'interrupt' = unterbrechen. Ein sog. Software-Interrupt unterbricht die Ausführung an der jeweiligen Stelle des Programms und ruft eine Funktion des Betriebssystems auf. Es wird hier 2x der Interrupt 21 (Befehl: 'int 21h') aufgerufen, welches der typische Einsprungpunkt für MSDOS-Kernelfunktionen ist. (ähnlich dem Interrupt 80 unter Linux). Der 'int'-Befehl benötigt aber verschiedene Angaben beim Aufruf (Parameter) und diese werden daher vor dem 'int'-Aufruf mit den 'mov'-Befehlen in die Register geschrieben. Im sog. A-Register (bei 16bit Intel Systemen heisst dieses 'AX', unterteilt in AH und AL) wird definiert, welcher Kernelbefehl ausgeführt werden soll. Beim 1. INT21 Aufruf wird also die Funktion Nr. 9 ausgeführt = Systemausgabe, beim 2. Aufruf wird die Funktion Nr. 4C aufgerufen = Programmende.

Erstellung:

Kompiliert wird das Programm mit folgenden Befehlen:

#> masm hello.asm hello.obj 
#> ml hello.obj

Anschließend können Sie es mit folgendem Befehl starten:

#> ./hello
#> Hello World

MASM: Das ist der hier verwendete Compiler für Assembler. MASM erstellt aus der Textdatei 'hello.asm', die den obigen Codetext enthält, die Objectcode-Datei 'hello.obj'.

ML: Das ist der sog. "Linker", der das endgültige Programm erstellt. Als Parameter wird einfach die obj-Datei angegeben. Daraus ergibts sich dann automatisch der Name des Programs (hello.exe).

Links: