Einsteigerproblem in Assembler mit NASM (und MASM)

Hallo zusammen!
Vor ein paar Tagen hatte ich hier euch schon mal wegen einer Anfrage zum Thema Assembler genervt. Jetzt habe ich mir ein Buch (Assembler / M. Roming u. J. Rohde / mitp-Verlag) besorgt und möchte Assembler richtig lernen. Das heißt ich bin auch noch ein echter Anfänger.
Als Assembler habe ich mir NASM Version 0.98.39 (für DOS) und MASM32 Version 8 besorgt, wobei ich lieber mit NASM arbeiten würde. Hierzu auch schon meine erste Frage: Kann NASM mit den entsprechenden LIBs auch Windows-Fenster erzeugen wie MASM?
Um den Umgang mit dem Assembler zu erlernen habe ich das erste Testprogramm aus dem oben genantem Buch abgeschrieben. Hier das Listing dazu:

.model small
.stack 100h
.data
meldung db „Hallo Welt$“
.code
start:
mov ax, @data
mov ds, ax
mov dx, offset meldung
mov ah, 09h
int 21h
mov ah, 4Ch
int 21h
end start

Beide Assembler haben mir keine EXE-Datei erzeugen können. So wie ich das verstehe hängt es nicht am Assembler selbst, sondern am Linker. Ich habe schon ein paar Codemodifikationen selbst ausprobiert, wie zum Beispiel die STACK-Deklaration wegzulassen, was aber alles nichts geholfen hat.

MASM-Eingabe: ml bsp.asm
MASM-Ausgabe:
Microsoft ® Macro Assembler Version 6.14.8444
Copyright © Microsoft Corp 1981-1997. All rights reserved.

Assembling: bsp.asm
Microsoft ® Incremental Linker Version 5.12.8078
Copyright © Microsoft Corp 1992-1998. All rights reserved.

/z2
„bsp.obj“
„bsp.exe“
NUL
LINK : warning LNK4044: unrecognized option „z2“; ignored
LINK : error : Segment reference in fixup record
bsp.obj : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt

NASM-Eingabe: nasm bsp.asm
NASM-Ausgabe:
bsp.asm:1: error: attempt to define a local label before any non-local labels
bsp.asm:1: error: parser: instruction expected
bsp.asm:2: error: attempt to define a local label before any non-local labels
bsp.asm:2: error: parser: instruction expected
bsp.asm:3: error: attempt to define a local label before any non-local labels
bsp.asm:9: error: comma or end of line expected
bsp.asm:14: error: parser: instruction expected

Meine Frage ist recht simpel: Wo liegt der Fehler? Den Quelltext habe ich schon mehrfach überprüft und den habe ich richtig abgetippt. Das heißt entweder liegt es am Programm selbst, oder an den Parametern für den Assembler.
Ich muss noch dazu sagen, dass das Buch nur TASM und MASM verwendet, ich aber lieber NASM verwenden würde, weil der auch unter Linux funktioniert. In dem Buch steht das man MASM mit der Option /c aufrufen soll, damit keine EXE-Datei sondern nur ein Objectfile erzeugt wird. Mit „link bsp.obj“ sollte dann der Linker die EXE-Datei erzeugen. Auch diese Vorgehensweise hat nicht zum Ziel geführt.

Grüße
C. Penkwitt

Hallo,
dass der MASM Code aus deinem Buch nicht mit NASM funktioniert ist nicht weiter verwunderlich, da die beiden Assembler einen unterschiedlichen Syntax verwenden. Obwohl das Grundprinzip natürlich gleich bleibt, ist der Unterschied doch relativ groß, so dass du dir zumindest überlegen solltest mit MASN anzufangen um die Beispiel in deinen Buch richtig nutzten zu können (Alternativ kannst du dir natürlich auch Demo-Code aus dem Internet besorgen). Obwohl NASM im Gegensatz zu MASM kaum HLL Elemente unterstützt, ist es natürlich möglich ein Fenster zu erstellen, man braucht dazu aber ein paar zusätzliche Dateien aus dem Internet. Ob es wirklich sinnvoll ist ein komplexeres Projekt vollständig in Assembler zu programmieren sei jedoch einmal dahin gestellt…

Der folgende Code sollte mit NASM funktionieren:

bits 16 ; DOS läuft im real-mode -\> 16bit

section .text ; Hier beginnt das code-segment
mov ax, cs ; Stelle sicher dass code-seg..
mov ds, ax ; und data-seg gleich sind

mov dx, meldung ; label = addresse, [label] = Wert
mov ah, 0x09 ; DOS system-call 
int 0x21 ; -\> Print string

cli ; Interrupts aus
hlt ; Anhalten (sonst geht das Fenster sofort wieder zu..)

mov ah, 0x4c ; DOS system-call
int 0x21 ; -\> return to dos ?

section .data ; Beginn des Datensegmentes
meldung db "Hallo Welt", "$"

Bezüglich deines Problems mit MASM kann ich dir leider nicht weiterhelfen, da ich diesen Assembler nie verwedet habe…

Grüße,
Daniel Raffler

Hallo Daniel!
Vielen Dank zu aller erst! Deinen Source-Code hat NASM anstandslos übersetzt. Dazu habe ich folgendes eingegeben: „nasm test.asm –o test.exe“
Danach habe ich test.exe gestartet und mit einem Piepton war das die Ausgabe:

¨:heart:¨:heart::slight_smile::slight_smile::slight_smile: :slight_smile: =:clubs:µ . ↑ . :clubs: ═!╦
î╚ÄÏ║ ┤ ═!·
┤L═! Hallo Welt
Das ist nicht ganz das was ich erwartet habe. Läuft da irgendwas schief oder mache ich etwas falsch?
Das der Unterschied zwischen NASM und MASM so groß ist hätte ich nicht gedacht. Kannst du darum ein spezielles Buch oder besser ein Online-Tutorial zu NASM empfehlen? Irgendwie musst du es ja auch gelernt haben … :smile:
Vielen Dank noch Mal!

Grüße
C. Penkwitt

Piepton gab es bei mir keinen, aber die Ausgabe hatte ich mir zugegebenermaßen auch etwas anders vorgestellt. Die Ursache das Problems war, dass ich die ORG-Direktive, welche die Startaddresse für die im Code verwendeten Symbole (Addressen von Variablen und Funktionen) darstellt, vergessen habe. Dadurch wird automatisch der Wert 0x00 angenommen und nicht 0x100 wie unter DOS üblich, so dass alle Symbole um 0x100 nach vorne verschoben waren. Bei dem Buchstabensalat vor der eigentlichen Nachricht handelt es sich also (zumindest im 2.Teil) um den Programmcode in ASCII-Form…
Abgesehen davon schein zumindest WinXP von meinem HLT-Befehl relativ unbeeindruckt zu sein. Ich habe in daher durch ein „jmp $“ ersetzt, so dass das Programm nach Ausgabe des Strings eine Endlosschleife ausführt, wodurch das Fenster offengehalten wird. Eleganter wäre es sicherlich die Schleife durch eine Tastaturabfrage zu ergänzen (Schleife endet wenn Taste gedrückt wird) oder zumindest den „Sleep“ Systemcall des entsprechenden Betreibssystems zu verwenden.

org 0x100

bits 16 ; DOS läuft im real-mode -\> 16bit

section .text ; Hier beginnt das code-segment
mov ax, cs ; Stelle sicher dass code-seg..
mov ds, ax ; und data-seg gleich sind

mov dx, meldung ; label = addresse, [label] = Wert
mov ah, 0x09 ; DOS system-call
int 0x21 ; -\> Print string

jmp $ ; '$' ist die aktuelle Position im code -\> Endlosschleife

mov ah, 0x4c ; DOS system-call
int 0x21 ; -\> return to dos ?

section .data ; Beginn des Datensegmentes
meldung db "Hallo Welt", "$"

Das der Unterschied zwischen NASM und MASM so groß ist hätte
ich nicht gedacht. Kannst du darum ein spezielles Buch oder
besser ein Online-Tutorial zu NASM empfehlen? Irgendwie musst
du es ja auch gelernt haben … :smile:
Vielen Dank noch Mal!

Die beiden Assembler unterscheiden sich zwar in ihren Syntax und teilweise auch im Funktionsumfang (NASM ist spartanischer), die eigentliche Sprache bleibt aber natürlich die selbe. Ich habe die Grundlagen selbst auch aus einem auf MASM basiereden Buch gelernt, den Assembler selbst aber nie benutzt.

Bezüglich e-books sollte dir folgender Link weiterhelfen:
http://www.osdcom.info/forum_viewtopic.php?4.303
Bei der win32 Programmierung fand ich Iczelion’s Seite (speziell das Forum) sehr nützlich:
http://win32assembly.online.fr/

Da ich ASM selbst nur zur Programmierung diverser Hobby-Betriebssysteme verwende, kann ich dir leider nicht sehr viele Links für DOS anbieten…

Grüße,
Daniel Raffler