Home

Programmbeispiel:
Frageprogramm

Tastatureingabe per Input-Befehl, etwas Fehlersuche
mit VKdebug sowie Ein- und Ausgabeumleitung

MASM32-
Infoseite

MASM32 SDK (Windows Konsole):
Die Messagebox MSGbox in Visual BASIC 2010 und im Masm32 SDK

Bild rechts: Auch im Konsolmodus lassen sich einige Anzeigen auf dem Bildschirm in einer Fensterdarstellung à la Windows realisieren. Es handelt sich um Anzeigen, die eine Bestätigung mit
  • OK,
  • Ja oder Nein,
  • Wiederholen, und/oder Abbrechen
erfordern. Der Programmablauf wird erst nach erfolgter Bestätigung fortgesetzt.
Bild: Ausgabebeispiel Nachrichtenbox bzw. MSGbox
Bild: Steuermöglichkeit der Nachrichtenbox bzw. MSGboxDie links dargestellte Anzeige einer Nachrichtenbox (MSGbox) zeigt eine Bedienungsanleitung. Sie wurde - ebenso wie die erste MSGbox auf dieser Seite - mit einem kleinen Programm erzeugt. Das Programm wurde in der Sprache Visual BASIC erstellt und ist weiter unten dargestellt.

Der sachliche Inhalt der links gezeigten MSGbox wurde aus einer Dokumentation von VBA5 (Visual BASIC for Applications Version 5) abgeleitet.

Die Anzeige der oben auf dieser Seite dargestellten MSGbox wurde mit dem in der Bedienungsanleitung enthaltenen Beispiel erzeugt. Dabei ist die bevorzugte Antwort "Ja" bereits hervorgehoben worden. Diese Hervorhebeung bzw. Vorauswahl wird über den Zahlenschlüssel 36 erreicht. Er ergibt sich aus der Bedienungsanleitung:

  • 32 = Das Fragezeichenbild wird gezeigt
  • 4 = 32 Die Schaltknöpfe für Ja und Nein erscheinen;
  • 0 = Der erste Schaltknopf soll vorgewählt werden.

Nach erfolgter Auswahl wird die Antwort Ja oder Nein per Errorlevel 7 oder 6 weitergegeben. Sie lässt sich beispielsweie mit einem geeigneten Batchprogramm auswerten.

Leider ist der Zeichencode bei der Konsoldarstellung anders als in der Windowsdarstellung. Der Notepad-Editor läuft in der Windowsdarstellung. Wir erstellen jedoch eine Konsolanwendung. Wenn man das Batchprogramm mit dem Notepad-Editor eintippt, hat man infolgedessen Ärger mit der Umlautdarstellung. Die deutschen Umlaute ä und ß müssen bei gedrückter ALT-Taste über das numerische Tastenfeld vierstellig eingetippt werden:
ä als 0132
ß als 0225

Der Dateiname kann z.B. teddy.bat heißen.

Im Notepad-Editor sieht die Datei dann so aus:

@echo off
:anfang
cmsgbox "Ist Teddy ein sehr groáer Grizzlyb„r?" 36 "Eine b„rige Frage
if errorleven == 7 goto antwortnein
if errorlevel ==6 goto antwortja

:antwortnein
cmsgbox "Die Antwort ist falsch.\Korrigieren Sie die Antwort!" 0 "Dumme Antwort"
goto anfang
 
:antwortja
cmsgbox "Ihre Antwort ist absolut korrekt.\\Mit b„rigem Gruá\Teddy" 64


Das Quellprogramm für Visual BASIC 2010
Eine kurze Interpretation zu diesem Programm steht unterhalb des Quellprogrammtextes.

Module Module1

Function Main(ByVal sArgs() As String) As Integer
   Dim strHELP As String
   Dim intButton As Integer = 64
   Dim strTitel As String = "MSGbox"
   Dim returnValue As Integer = 0
   Const vbQuote = Chr(34)

   If sArgs.Length = 0 Then                'Falls kein Aufrufargument angegeben wurde
      strHELP = "Syntax: MSGbox Prompt[, Schaltknopf][,Titel]\"
      strHELP = strHELP & "Beispiel: CMSGbox " & vbQuote & "Ist Teddy ein sehr großer Grizzlybär?" _
         & vbQuote & " 36 " & vbQuote & "Eine bärige Frage" & vbQuote & "\\"
      strHELP = strHELP & "Prompt: Text, der in der Benachrichtigung erscheinen soll."
      strHELP = strHELP & " Jeder enthaltenen Backslash wird als Zeilenwechsel interpretiert.\"

      strHELP = strHELP & "Schaltknopf: Summe der Auswahlzahlen."
      strHELP = strHELP & " Damit lassen sich Schaltknöpfe und Icons erzeugen.\\"
      strHELP = strHELP & "0 = Schaltknopf OK wird gezeigt\"
      strHELP = strHELP & "1 = Schaltknöpfe OK und Abbrechen(Cancel) werden gezeigt\"
      strHELP = strHELP & "2 = Schaltknöpfe Abbrechen (Abort),"
      strHELP = strHELP & " Wiederholen und Ignorieren werden gezeigt\"
      strHELP = strHELP & "3 = Schaltknöpfe Ja, Nein und Abbrechen (Cancel) werden gezeigt\"
      strHELP = strHELP & "4 = Schaltknöpfe Ja und Nein werden gezeigt\"
      strHELP = strHELP & "5 = Schaltknöpfe Wiederholen und Abbrechen (Cancel) werden gezeigt\"
      strHELP = strHELP & "16 = Icon kritische Nachricht (Stopzeichen) wird gezeigt\"
      strHELP = strHELP & "32 = Icon Warnung/Frage (Fragezeichen) wird gezeigt\"
      strHELP = strHELP & "48 = Icon Gefahr (Gefahrenzeichen) wird gezeigt\"
      strHELP = strHELP & "64 = Icon Information (Informationszeichen) wird gezeigt\"
      strHELP = strHELP & "0 =    Defaultauswahl ist der erste Schaltknopf\"
      strHELP = strHELP & "256 =  Defaultauswahl ist der zweite Schaltknopf\"
      strHELP = strHELP & "512 =  Defaultauswahl ist der dritte Schaltknopf\"
      strHELP = strHELP & "768 =  Defaultauswahl ist der vierte Schaltknopf\"
      strHELP = strHELP & "0 =    Nachrichtenbox einer Applikation\"
      strHELP = strHELP & "4096 = Nchrichtenbox des Systems\\"

      strHELP = strHELP & "Titel: Text für die Titelzeile der Nachrichtenbox\\"

      strHELP = strHELP & "Der Errorlevel bei Programmende gibt an,"
      strHELP = strHELP & " welcher Schaltknopf betätigt wurde:\"
      strHELP = strHELP & "1 = OK\"
      strHELP = strHELP & "2 = Abbrechen (Cancel)\"
      strHELP = strHELP & "3 = Abbrechen (Abort)\"
      strHELP = strHELP & "4 = Wiederholen\"
      strHELP = strHELP & "5 = Ignorieren\"
      strHELP = strHELP & "6 = Ja\"
      strHELP = strHELP & "7 = Nein\"
   Else
      strHELP = sArgs(0)
   End If

   If sArgs.Length >= 3 Then strTitel = sArgs(2)

   If sArgs.Length >= 2 Then intButton = Val(sArgs(1))

   returnValue = MsgBox(Replace(strHELP, "\", vbCrLf), intButton, strTitel)

   'Die nachfolgenden Kommentarzeilen sind ehemalige Testhilfen 
   'MsgBox("The application is terminating with error level " & CStr(returnValue) & ".")
   'Console.WriteLine(intButton)
   'Console.Write("Beenden mit Enter-Taste ... ")
   'Do While Console.ReadKey().Key <> ConsoleKey.Enter
   'Loop

    Return returnValue
    End Function
End Module

Interpretation des Quellprogramms für Visual BASIC 2010
Function Main(ByVal sArgs() As String) As Integer: Üblicherweise starten Visual BASIC-Programme mit SUB Main. Aber dies Programm soll eine Ganzzahl (Integer) für den Errorlevel zurückgeben. Deshalb wird es mit Function Main gestartet. Die eingeklammerten Angaben dienen zum Einlesen der Kommandozeile.

If sArgs.Length = 0 Then: aArgs.Lenth enthält 0 sofern keinerlei Parameter mitgegeben wurden. In diesem Fall wird durch mehrfache Verkettung die sehr lange Zeichenkette strHELP gebildet. Sie enthält die Bedienunganleitung für das Programm. Spätere Zeilenvorschübe sind als Backslash (\) enthalten.

strHELP = sArgs(0): Hier wird der erste Parameter übernommen. Er ist über sArgs(0) ansprechbar. Nur wenn sie vorhanden sind überschreiben die beiden folgenden Parameter überschreiben die am Programmanfang voreingestellten Werte. Um das Vorhandensein festzustellen, wird jeweils sArgs.Length abgefragt.

returnValue = MsgBox(Replace(strHELP, "\", vbCrLf), intButton, strTitel): Der Rückgabewert (Errorlevel) aus dem rechts neben dem Zuweisungszeichen(=) angeforderten Funktion MSGbox wird der Variablen returnValue zugewiesen. Zum Programmende wird somit der Rückgabewert mit Return returnValue exportiert.



Die Messagebox MSGbox in Masm32
Bild: Nachrichtenbox bzw. MSGboxEs ist gar nicht kompliziert, eine MSGbox in ein Masm32-Konsolprogramm einzubauen. Das folgende Programm ist eine geringfügige Modifikation aus Iczelion's Tutorial No.2.

Bild links: Hier erfolgt die Textausgabe ohne das runde Icon links vor dem Text, weil beim Aufruf invoke MessageBox als lezter Parameter 3 angegeben wurde.

Es gibt einen internen Unterschied: Bei Masm32 erfolgt die Ausgabe einer Messagebox über die sogenannte API-Funktion Messagebox.

.586 
.model flat,stdcall 
.xlist
option casemap:none 
include \masm32\include\windows.inc 
include \masm32\include\user32.inc 
include \masm32\include\kernel32.inc

includelib \masm32\lib\user32.lib  
includelib \masm32\lib\kernel32.lib
.list
.data
consoleOutHandle dd ? 
MsgBoxCaption  db "Iczelion Tutorial No.2",0 
MsgBoxText     db "damit kann auch Teddy mit",13,10,"Win32 Assembler programmieren",0
LMsgBoxText    equ $-MsgBoxText-1   ;Laenge ohne die nachlaufende 0

.code 
start:  INVOKE GetStdHandle, STD_OUTPUT_HANDLE
        mov consoleOutHandle, eax
        invoke MessageBox, consoleOutHandle, addr MsgBoxText, addr MsgBoxCaption, 3
        invoke ExitProcess, eax 
end start
Fehlerhinweis: Es hat sich gezeigt, dass bei Verwendung des ermittelten Handles die Anzeige der Messagebox nicht in jedem Fall erfolgt. So geht es besser:
       invoke MessageBox, 0, addr MsgBoxText, addr MsgBoxCaption, 3

Interpretation des Quellprogramms für MASM32
Damit bei den Labelnamen zwischen Groß- und Kleinschreibung unterschieden wird, muss die option casemap:none eingetragen sein.

Ein sogenannter Prototyp beschreibt das Aufrufformat für die Messagebox so:

MessageBox PROTO hwnd:DWORD, lpText:DWORD, lpCaption:DWORD, uType:DWORD

  • hwnd ist das ermittelte Handle des Konsolfensters.
  • lpText zeigt auf den in der Messagebox anzuzeigenden Textstring.
  • lpCaption zeigt auf den Textstring für die Titelzeile. Beide Strings müssen mit einer 0 abgeschlossen werden.
  • uType ist die in der großen MSGbox oben auf dieser Webseite genannte Summe der Auswahlzahlen für Schaltknöpfe und Icons. Im Masm32 SDK werden für die Auswahlzahlen sogar Symbole bereitgestellt!
  • MSGBoxText: Die Bytefolge 13,10 bewirkt einen Zeilenvorschub in der Ausgabe.
  • LMsgBoxText: Das $-Zeichen wird als sogenannter Zuordnungszähler interpretiert. Mit diesem Ausdruck wird die Laenge der auszugebenden Zeichenfolge ohne die nachlaufende 0 berechnet. Die ermittelte Länge wird mit dem Namen LMsgBoxText ausgestattet. Den so geschaffenen Namen kanman im Quellprogramm verwenden. Für dies Programm ist diese Befehlszeile jedoch nicht erforderlich.
  • invoke MessageBox, consoleOutHandle, addr MsgBoxText, addr MsgBoxCaption, 3
    Aufgelöst ergibt dies Macro:
    push 3
    push OFFSET MsgBoxCaption,
    push OFFSET MsgBoxText
    push consoleOutHandle
    call MessageBox
Die Anzeige der MSGbox wird mit einem invoke-Macro aufgerufen. Das darauf folgende weitere Invoke-Macro invoke ExitProcess, eax exportiert den aus dem Unterprogramm MessageBox im Register EAX übergebenen Errorcode bzw. Errorlevel. Es handelt sich um das im Iczelion-Tutorial empfohlene Verfahren.


Ein alternatives Quellenprogramm mit Verwendung der Macrobibliothek macros.asm
In der beim Masm32 SDK mitgelieferten Datei \masm32\macros\macros.asm ist das Macro MsgBox enthalten. Es ermöglicht die Angabe von in Gänsefüßchen oben eingekleideten Zeichenketten für die Überschrift und den Text der Messagebox. In unserem Fall lässt sich diese nur für die Überschrift nutzen, denn für die Definition des Textes sind aufgrund des Zeilenumbruchs vier Gänsefüßchen oben erfoderlich.

Hier gibt es zwei Lösungen:

  • Auf den Text mit den Steuerzeichen wird im Macro MsgBOx ohne Gänsefüßchen verwiesen:
    MsgBox 0,addr MsgBoxText,"Iczelion Tutorial No.2",3
  • Die Anwendung von chr$:
    MsgBox 0,chr$("damit kann auch Teddy mit",13,10,"Win32 Assembler programmieren"),\
     "Iczelion Tutorial No.2",19
    Der Backslash am Zeilenende besagt, dass die folgende Zeile die aktuelle Zeile fortsetzt.

.586 
.model flat,stdcall

option casemap:none 
include \masm32\include\windows.inc 
include \masm32\include\user32.inc 
include \masm32\include\kernel32.inc
include \masm32\macros\macros.asm

includelib \masm32\lib\user32.lib  
includelib \masm32\lib\kernel32.lib
.list
.data
;MsgBoxText     db "damit kann auch Teddy mit",13,10,"Win32 Assembler programmieren",0

.code 
start:  
;    MsgBox MACRO hndl,txtmsg,titlemsg,styl
;      invoke MessageBox,hndl,reparg(txtmsg),reparg(titlemsg),styl
;    ENDM        
;       MsgBox 0,addr MsgBoxText,"Iczelion Tutorial No.2",3
        MsgBox 0,chr$("damit kann auch Teddy mit",13,10,"Win32 Assembler programmieren"),\
        "Iczelion Tutorial No.2",19
        invoke ExitProcess, eax         
end start

Letztes Upload: 30.03.2017 um 14:31:28