Liste von Hallo-Welt-Programmen/Assembler

Diese Liste von Hallo-Welt-Programmen von Assemblersprachen enthält kleine Computerprogramme, die auf einfache Weise zeigen, welche Anweisungen für ein vollständiges Programm in einer Programmiersprache benötigt werden.

Zweck

Aufgaben dieser Hallo-Welt-Programme ist, den Text Hallo Welt! in einem einfachen Programm auszugeben. Weitere Programme sind verfügbar:

x86-CPU

DOS (COM-Datei), MASM, TASM

.MODEL Tiny
.CONST
 HW     DB      "Hallo Welt!$"
.CODE
.org 100h
start:
  MOV DX, OFFSET DGROUP:HW
  MOV AH, 09H
  INT 21H
  RET
end start

DOS (EXE-Datei), MASM, TASM

.MODEL Small
.STACK 100h
.CONST
  HW      DB      "Hallo Welt!$"
.CODE

start:
  MOV AX,@data
  MOV DS,AX
  MOV DX, OFFSET DGROUP:HW
  MOV AH, 09H
  INT 21H
  MOV AH, 4Ch
  INT 21H
end start

DOS, FASM

'''FASM example of writing 16-bit DOS .COM program'''
; Kompilieren: "FASM HELLO.ASM HELLO.COM"
  org  $100
  use16
  mov  ah,9
  mov  dx,hello
  int  $21    ; Textausgabe
  mov  ah,$4C
  int  $21    ; Programm beenden
hello db 'Hallo Welt !!!$'

Windows, FASM

; Ausgabe in Messagebox (ohne Titel) mit OK-Button

include 'win32ax.inc'

.code

  start:
        invoke  MessageBox,HWND_DESKTOP,text,"",MB_OK
        invoke  ExitProcess,0

.end start

.data

text:   db "Hallo Welt!",0

Linux

AT&T-Syntax

# Kompilieren mit
# "as -o hallo.o hallo.s; ld -o hallo hallo.o"

    .section .data
s: .string "Hallo Welt!\n"

    .section .text
    .globl _start
_start:
    movl $4,%eax      # Syscall-ID 4 (= sys_write)
    movl $1,%ebx      # Ausgabe-Dateideskriptor stdout (= 1)
    movl $s,%ecx      # Adresse des ersten Zeichens der Zeichenkette
    movl $12,%edx     # Länge der Zeichenkette (12 Zeichen)
    int $0x80         # Softwareinterrupt 0x80, um Syscall (write(1,s,12)) auszuführen

    movl $1,%eax      # Syscall-ID 1 (= sys_exit)
    movl $0,%ebx      # Rückgabewert 0 (= alles in Ordnung)
    int $0x80         # Softwareinterrupt 0x80 um Syscall (exit(0)) auszuführen

Intel-Syntax

; Befehl zum Assemblen: nasm -felf hello.s
;                  && ld -o hello hello.o
    section data
hello db  "Hallo Welt!",0xa
len   equ $-hello

    section text
    global  _start
_start:
    mov eax, 4 ; write(stdout, hello, len)
    mov ebx, 1
    mov ecx, hello
    mov edx, len
    int 80h

    mov eax, 1 ; exit(0)
    mov ebx, 0
    int 80h

x86-CPU, FreeBSD, Intel-Syntax

  section .data
    hello_world db 'Hallo Welt!', 0x0a
    hello_world_len equ $ - hello_world
  section .text
    align 4
    sys:
      int 0x80
      ret
    global _start
    _start:
      push hello_world_len
      push hello_world
      push 1
      mov eax, 4
      call sys
      push 0
      mov eax, 1
      call sys

PowerPC-CPU, Linux

   # Kompilieren mit "gcc -nostdlib -s hallo.s"
       .section    .rodata
       .align 2
   .s:
       .string "Hallo Welt!\n"

       .section    ".text"
       .align 2
       .globl _start
   _start:
       li 0,4          # SYS_write
       li 3,1          # fd = 1 (stdout)
       lis 4,.s@ha     # buf = .s
       la 4,.s@l(4)
       li 5,12         # len = 12
       sc              # syscall

       li 0,1          # SYS_exit
       li 3,0          # returncode = 0
       sc              # syscall

MMIX, MMIXAL

 string  BYTE  "Hallo Welt!",#a,0  % auszugebende Zeichenkette (#a ist ein Zeilenumbruch,
                                   % 0 schließt die Zeichenkette ab)
 Main    GETA  $255,string         % Adresse der Zeichenkette in Register $255 ablegen
         TRAP  0,Fputs,StdOut      % Zeichenkette, auf die mit Register $255
                                   % verwiesen wird, nach ''StdOut'' ausgeben (Systemaufruf)
         TRAP  0,Halt,0            % Prozess beenden

680x0-CPU, Amiga

           ; Getestet mit ASM-One V1.01
           move.l  4.w,a6
           lea     dosn(pc),a1
           jsr     -408(a6)        ; OldOpenLibrary

           move.l  d0,a6
           lea     s(pc),a0
           move.l  a0,d1
           jsr     -948(a6)        ; PutStr

           move.l  a6,a1
           move.l  4.w,a6
           jsr     -414(a6)        ; CloseLibrary
           moveq   #0,d0
           rts
   dosn:   dc.b    "dos.library",0
   s:      dc.b    "Hallo Welt!",10,0

PA-RISC-CPU, HP-UX

   ; Kompiliert und getestet mit
   ; "as hallo.s ; ld hallo.o /usr/ccs/lib/crt0"
   ; unter HP-UX 11.0 auf einer HP9000/L2000
           .LEVEL 1.1
           .SPACE $TEXT$
           .SUBSPA $LIT$,ACCESS=0x2c
   s       .STRING "Hallo Welt!\x0a"

           .SPACE $TEXT$
           .SUBSPA $CODE$,ACCESS=0x2c,CODE_ONLY
           .EXPORT _start,ENTRY,PRIV_LEV=3
           .EXPORT __errno
           .EXPORT __sys_atexit
   _start
   __errno
   __sys_atexit
           ldil    L'0xC0000000,%r18
           ldi     4,%r22                  ; SYS_write
           ldi     1,%r26                  ; fd = stdout
           ldil    LR's,%r4
           ldo     RR's(%r4),%r25          ; buf = s
           be,l    4(%sr7,%r18)            ; Syscall
           ldi     12,%r24                 ; len = 12 (Branch delay slot)

           ldi     1,%r22                  ; SYS_exit
           be,l    4(%sr7,%r18)            ; Syscall
           ldi     0,%r26                  ; returncode = 0 (Branch delay slot)

SPARC-CPU, Linux

; Kompilieren mit "as -o hallo.o hallo.s; ld -o hallo hallo.o"
.section .data

hello_str:
    .asciz "Hallo Welt!\n"
    .align 4                ; Speicher muss aligned sein, damit wir später mit ld darauf zugreifen können
hello_str_len:
    .word . - hello_str     ; Länge der Zeichenkette (12 Zeichen)

.section .text

.global _start
_start:
    set 4, %g1              ; Syscall-ID 4 (= __NR_write)
    set 1, %o0              ; Ausgabe-Filedeskriptor STDOUT (= 1)
    set hello_str, %o1      ; Adresse des ersten Zeichens der Zeichenkette
    set hello_str_len, %l0  ; Die Stack-Adresse, an der die Länge der Zeichenkette steht, in local 0 laden
    ld [%l0], %o2           ; Den Wert auf den local 0 zeigt in out 2 laden
    t 0x110                 ; Softwareinterrupt 0x110 um Syscall (write(1,hello_str,hello_str_len))auszuführen
    set 1, %g1              ; Syscall-ID 1 (= __NR_exit)
    set 0, %o0              ; Rückgabewert 0 (= alles ok)
    t 0x110                 ; Softwareinterrupt 0x110 um Syscall (exit(0)) auszuführen

Assemblersprache (Jasmin)

; HelloWorld.j

.bytecode 50.0
.source HelloWorld.java
.class public HelloWorld
.super java/lang/Object

.method public <init>()V
  .limit stack 1
  .limit locals 1
  aload_0
  invokespecial java/lang/Object/<init>()V
  return
.end method

.method public static main([Ljava/lang/String;)V
  .limit stack 2
  .limit locals 1
  getstatic java/lang/System/out Ljava/io/PrintStream;
  ldc "Hallo Welt!"
  invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
  return
.end method

MIPS-32 mit erweitertem Befehlssatz

# Emulation mit 'spim -f hw.asm'
.data
	helloworld: .asciiz "Hallo Welt!\n"   # 'z' in asciiz für Null-terminierter-string

.text
main:
	la $a0, helloworld                    # lade Adresse von helloworld
	li $v0, 4                             # print_string
	syscall

	li $v0, 10                            # Betriebssystem exit-Routine
	syscall

Arm-Armv7l, Linux

.text

.global _start

_start:

        /* print */
        mov     r2, $11
        ldr     r1, =hw
        mov     r0, $1
        mov     r7, $4
        svc     $0

        /* exit */
        sub     r0, r0, r0
        mov     r7, $1
        svc     $0

.data

hw:
.ascii "Hallo Welt\n"

TAS (Telefunken-Assembler-Sprache)

TAS

--- Hallo Welt am TR440 --
HALLO.=SEGM,
START HALLO, ALARM CIAO, XBASIS INDIZES, UNTPR 7, VORBES (1,0) -- Einzelheiten zum Programmstart --
INDIZES=ASP 256/G -- Indexspeicher ist Teil des Arbeitsspeichers --
VB616=CIAO/AG, 3/H, TXT/A, 2/H, 0 -- Einzelheiten für SSR 6 16 --
TXT=''*021Hello World'',
XBA VB616, SSR 6 16 -- Text ausgeben --
CIAO=      SSR 0 12 -- Programmlauf beenden --
ENDE,
  • Die Sprache ist weitgehend formatfrei: Informationseinheiten (Befehle und Pseudobefehle) werden durch Kommata oder Kommentare begrenzt.
  • Kommentare werden zwischen doppelte Minuszeichen eingeschlossen.
  • Ein Kommentar, der mit drei Minuszeichen beginnt, wirkt als Seiten-Überschrift im Assembler-Protokoll.
  • Das Betriebssystem benötigt zum Programmstart fünf Angaben: die Start-Adresse, die Alarm-Adresse (Fortsetzung des Programms nach einem Alarm), Anfangswert der Register BXB und BU, Inhalt des freien Arbeitsspeichers.
  •  Systemdienste werden mit dem SSR-Befehl aufgerufen.
  • Konstanten (wie VB616) und Variable (wie INDIZES) werden im Kompilat automatisch getrennt von den Befehlen abgelegt; daher bezeichnet HALLO den XBA-Befehl (den ersten Befehl in der vorliegenden Quelle).

 TASR

--- Hallo Welt am TR440 --
HALLO.=SEGM,
R&DRUCKETEXT (''Hello World!'') -- Text ausgeben --
R&ENDE -- Programmlauf beenden --
ENDE,
  • TASR bietet einen Rahmen für TAS-Programme, die im Normalmodus ablaufen, und stellt Makros für häufig benötigte Systemdienste zur Verfügung.
  • Die 5 Angaben zum Programmstart entfallen, da sie im Rahmenprogramm enthalten sind.
  •  Alle in diesem Beispiel benötigten Systemdienste können durch Makro-Aufrufe erledigt werden.

IBM-Mainframe-ASSEMBLER

HALLOW   CSECT
*
*****************************************************************
*        ASSEMBLER-PROGRAMM FUER IBM-MAINFRAME MIT
*        STANDARD-REGISTERSICHERUNG, LAUFFAEHIG UNTER
*        DEN GAENGIGEN KLASSISCHEN MAINFRAME-BETRIEBSSYSTEMEN
*        (ALSO JEDENFALLS Z/OS UND Z/VM UND DEREN VORLAEUFERN)
*****************************************************************
*
         STM   14,12,12(13)      REGISTER SICHERN
         LR    12,15             ENTRYPOINT KOPIEREN NACH REG 12
         USING HALLOW,12         BASISADR = ENTRY POINT
         LA    2,SAVEAREA        NEUE SAVE AREA EINSTELLEN
         ST    2,8(13)           VORWAERTSVERKETTUNG SAVE AREAS
         ST    13,4(2)           RUECKWAERTSVERKETTUNG SAVE AREAS
         LR    13,2              NEUE SAVE AREA NACH REG 13
*
         OPEN  (AUSGABE,OUTPUT)  DD:SYSPRINT AUFMACHEN
         PUT   AUSGABE,BUFFER    AUSGABE: HALLO WELT!
         CLOSE AUSGABE           DD:SYSPRINT ZUMACHEN
*
         L     13,4(13)          ALTE SAVE AREA WIEDER EINSTELLEN
         LM    14,12,12(13)      REGISTER ZURUECKLADEN
         XR    15,15             RETCODE AUF NULL
         BR    14                RUECKSPRUNG
*
SAVEAREA DS    18F               SAVE AREA
*
AUSGABE  DCB   DSORG=PS,MACRF=PM,DDNAME=SYSPRINT,RECFM=FBA,LRECL=133
*
BUFFER   DC    CL133' HALLO WELT!'
*
         END   HALLOW

Der Programmcode wird in festgelegten Spaltengrenzen erfasst.

  • Spalte 1–8 = Namensfeld (Feldbezeichnung oder Sprungziel)
  • Stern in Spalte 1 = Kommentarzeile (neuerdings ist es auch möglich, Zeilen komplett leer zu lassen)
  • in Spalte 10 beginnend = Befehlscode
  • in Spalte 16 beginnend = Operanden, dahinter (nach Leerstelle) optional beliebige Kommentare
  • Spalte 72 = Fortsetzung in der nächsten Zeile, wenn hier ein Zeichen ungleich Blank steht (nötig für lange Literale und Makros mit vielen Parametern)
  • die Fortsetzung erfolgt ggf. in der nächsten Zeile immer in der Spalte 16
  • Spalte 73–80 = Kennung oder lfd. Nummerierung (optional)

Tatsächlich sind die Spaltengrenzen heute etwas flexibler; z. B. gibt es heute Namen mit mehr als 8 Zeichen; dann beginnen die Befehlscodes nicht in Spalte 10, sondern später. Genauso können die Parameter auch nach Spalte 16 beginnen. Die Regeln sind wie folgt:

  • Ein Name muss immer in Spalte 1 beginnen, wenn vorhanden
  • wenn kein Name vorhanden ist, kommt der Befehlscode frühestens in Spalte 2, ansonsten muss er vom Namensfeld durch mindestens ein Blank abgetrennt sein
  • genauso bei den Operanden, sie müssen durch mindestens ein Blank vom Befehlscode abgetrennt sein
  • und die Kommentare müssen durch mindestens ein Blank von den Operanden abgetrennt sein
  • Blanks in Hochkommas zählen dabei nicht (siehe oben die Blanks im String ' HALLO WELT!' in der mit BUFFER markierten Anweisung)
  • wenn ein Befehl keine Operanden braucht, kann man ersatzweise ein einfaches Komma codieren

6502-CPU, C64

;Hello World for 6502 CPU (C64)
;Assembler used: win2c64
    LDY #$00      ;init loop counter
L0
    LDA L1,Y      ;load a byte of the text
    BEQ L2        ;if zero -> end
    JSR $FFD2     ;call CHROUT
    INY           ;inc loop counter
    JMP L0        ;thanks to paul nicholls
L1
    .byte "hello world",0
L2
    RTS

8048-CPU, Philips G7000

start
        call    gfxoff              ; switch the graphics off
        mov     r0,#vdc_char0       ; start char
        mov     r3,#20h             ; x-position
        mov     r4,#20h             ; y-position
        mov     r2,#0Bh             ; length
        mov     r1,#hellostr & 0FFh ; the string to print
                                    ; must be in the same page
loop    mov     a,r1                ; get pointer
        movp    a,@a                ; get char
        mov     r5,a                ; into to right register
        inc     r1                  ; advance pointer
        mov     r6,#col_chr_white   ; colour
        call    printchar           ; print it
        djnz    r2,loop             ; do it again
        call    gfxon               ; lets see what is written
stop    jmp     stop                ; Thats all
hellostr db     1Dh, 12h, 0Eh, 0Eh, 17h, 0Ch
         db     11h, 17h, 13h, 0Eh, 1Ah

Z80-CPU, Amstrad CPC

		ld hl,text              ; address of text into hl
loop:	ld a,(hl)               ; load akku by content at address in hl
		cp 0                    ; compare to zero
		ret z                   ; return if zero
		call &bb5a              ; otherwise print char in akku
		inc hl                  ; hl=hl+1
		jr loop                 ; relative jump to loop
text:	db "Hello World!",0     ; text with 0 as end mark