PofoWiki

Die ultimative Informationsquelle zum ATARI Portfolio

Benutzer-Werkzeuge

Webseiten-Werkzeuge


software:diy:assembler:aes

Dies ist eine alte Version des Dokuments!


AES-Programmierung

AES steht für Application Environment Services, sie sind Bestandteil von Portfolios Betriebssystem und im BIOS-ROM gespeichert.
Die AES sorgen für die Ausführung der Portfolio-spezifischen Funktionen wie Benutzeroberfläche, Wählfunktion, Kartenformatierung u.s.w. Sie werden über die Interrupts 60H und 61H aufgerufen. Eine komplette Übersicht ist im Technischen Referenzhandbuch zu finden, im Folgenden werden Beispiele für die Programmierung der wichtigsten Funktionen aufgeführt:

  • Zeilen-Editor
  • Menüs FIXME
  • Meldungen
  • Wählton
  • Melodie-Töne FIXME
  • DAT-Dateien FIXME

Zeilen-Editor

Der Zeilen-Editor wird mit der Funktion 01h des Interrupt 60h aufgerufen, vorher muss aber eine Datenstruktur definiert und initialisiert werden, dort sind die Werte für Bildschirmposition und Darstellung, sowie viele, für die Funktion wichtige Daten enthalten. Im Technischen Referenzhandbuch wird folgende Struktur angegeben:

  EP_TARG DW 2 DUP (?)	;Adresse der Zeichenkette
  EP_POS  DW (?)	;Position innnerhalb der Kette
  EP_MAX  DW (?)	;max. Länge der Kette
  EP_XPOS DB (?)	;Cursor-Position. Spalte.
  EP_YPOS DB (?)	;Cursor-Position. Zeile.
  EP_MODE DB (?)	;Zeichenkette löschen?
  EP_HIT  DW (?)	;Pre-Processing
  EP_TIT  DW 2 DUP (?)	;Adresse der Überschrift und Eingabeaufforderung
  EP_EXIT DW 2 DUP (?)	;Adresse der Liste für Ausstiegstasten
  EP_FN   DW 2 DUP (?)	;Adresse der Routine für Tastaturabfrage
  EP_WID  DB (?)	;max. Länge des Editier-Bereichs
  EP_WIND DB (?)	;Rahmen-Typ (0FFh=keiner,0=einfach,1=doppelt)
  EP_RES  DW 2 DUP (?)	;reserviert! Nicht verändern.
  EP_UDEL DW 2 DUP (?)	;Adressse der Undelete-Routine


Der Zeileneditor erwartet, dass alle Doppelwort-Zeiger mit dem niederen Word voran angegeben sind, das heißt erst der Offset, dann das Segment (OFS:SEG).

Datenstruktur

EP_TARG ist ein Doppelwort-Zeiger auf die Adresse der zu bearbeitenden Zeichenkette in der Form OFS:SEG.
Beispiel:

EDSTR   DB "Diese Zeile bearbeiten",0
.
.
.
MOV EP_TARG[0],OFFSET EDSTR 
MOV EP_TARG[2],CS

Die zu bearbeitende Zeile muss immer NULL-terminiert sein. Das heißt auch, dass man für die Speicherung der Kette immer ein Byte mehr reservieren sollte.


EP_POS ist ein Versatz innerhalb der Zeichenkete an der sich der Cursor beim Aufruf befinden soll. Das Editieren erfolgt dann ab dieser Stelle.
Beispiel:

MOV EP_POS,6

Der Cursor steht im oberen Beispiel nach dem Aufruf auf dem „Z“ (das „D“ ist Stelle 0).


EP_MAX ist die maximale Länge die die Zeichenkette während der Bearbeitung erreichen kann. Damit diese nicht überschritten werden kann, blockiert der Zeilen-Editor die Eingabe, außer für Entf, die Rücktaste und für die in der Liste der Austiegstasten definierten Tasten-Codes.

MOV EP_MAX,20

Die Zeichenkette ist somit auf 20 Zeichen begrenzt, es können keine weiteren Zeichen eingefügt werden, es sei denn man löscht vorher Zeichen mit Entf oder der Rücktaste.


EP_XPOS und EP_YPOS enthalten die Werte für die Bildschirm-Position des Eingabebereichs (mit oder ohne Rahmen). EP_XPOS muss zwischen 0 und 39 (Spalte), EP_YPOS zwischen 0 und 7 (Zeile) liegen. Die beiden Werte definieren die linke obere Ecke des Bereichs, der Programmierer muss dafür sorgen, dass die Werte nicht überschritten werden. Das Bearbeiten einer 10-stelligen Zeichenkette sollte z.B. nicht bei EP_XPOS größer als 29 beginnen, es sei denn der Editier-Bereich (EP_WID) ist kleiner als 10. Mehr dazu später.
Beispiel:

MOV EP_XPOS,4
MOV EP_YPOS,3

Der Bearbeitungsbereich beginnt in der fünften Spalte und der vierten Zeile. Wird ein Rahmen verwendet (EP_WIND = 0 oder 1), so ist dessen linke obere Ecke an dieser Position und die Bearbeitung beginnt in der fünften Zeile und der sechsten Spalte. Ist für die Eingabe ein Prompt angegeben (EP_TIT), so verschiebt sich der Eingabe-Bereich um die entsprechende Anzahl Spalten nach rechts. Mehr dazu später.


EP_MODE bestimmt, ob bei einer Eingabe (außer den Cursor-Tasten) die Zeile gelöscht wird oder nicht. Ist EP_MODE=2, so wird die Zeile bei einem Tastendruck nicht gelöscht, ist EP_MODE=0FFh, so wird die Zeile gelöscht, es sei denn, man betätigt zuerst die Cursor-Tasten.
Beispiel:
In den internen Anwendungen ist EP_MODE=2, wenn ein Dateiname (Speichern, Laden..) abgefragt wird. EP_MODE ist 0FFh, wenn eine Eingabe in einer Zelle der Tabellenkalkulation erfolgt.
Das Aktivieren des Rahmens ist beim Initialisieren von EP_XPOS, EP_YPOS und EP_WID zu berücksichtigen, der Cursor steht dann bei EP_XPOS+1 und EP_YPOS+1, und EP_WID sollte um 2 erhöht werden.


EP_HIT ist der Anfangs-Tastendruck der zu verarbeiten ist, bevor ein Benutzer-Tastendruck erfolgt. Wenn 0, dann findet keine Vor-Verarbeitung statt. FIXME


EP_TIT ist ein Doppelwort-Zeiger auf die Überschrift und Eingabeaufforderung des Eingabe-Bereichs, die verwendet werden, wenn der Rahmen eingeschaltet ist (EP_WIND = 0 oder 1).
Beispiel:

TIT 	DB "Titel",0,"Eingabe: ",0,0
.
.
.
MOV EP_TIT[0],OFFSET TIT
MOV EP_TIT[2],DS

Falls ein Rahmen (einfach oder doppelt) aktiviert ist, so steht in der oberen Leiste des Rahmens der Titel, und am linken Rand innerhalb des Rahmens die „Eingabe“. Wenn eine Eingabe-Aufforderung angegeben ist, so ist dies beim Initialisieren von EP_YPOS und EP_WID von Bedeutung, der sichtbare Bereich wird um die Länge der Aufforderung kürzer.


EP_EXIT ist ein Doppelwort-Zeiger auf eine Liste von Tasten-Codes, die die Eingane-Routine beeenden. Diese Liste besteht aus 16Bit-Werten. Wenn das höherwertige Byte = 0 ist, so steht der ASCII-Wert im niederwertigen Byte. Wenn das höherwertige Byte nicht 0 ist, so handelt es sich um einen erweiterten Tastencode (z.B. 0148h für die linke Cursor-Taste).
Beispiel:

EXIT_KEYS  DW  000Dh,001Bh,00h,00h
.
.
.
MOV EP_EXIT[0],OFFSET EXIT_KEYS
MOV EP_EXIT[2],DS

In diesem Fall führen nur die Eingabe-Taste und die Escape-Taste zur Beendung der Routine. Die Liste muss NULL-terminiert sein.


EP_FN ist ein Doppelwort-Zeiger auf die Routine der Tastatur-Abfrage. Im Beispiel-Programm heißt die Prozedur GET_KEY.

GET_KEY      PROC
 .
 .
 .
RETF
.
.
.
MOV AX,GET_KEY
MOV EP_FN[0],AX
MOV EP_FN[2],CS

Im Beispiel-Programm wird die Routine näher beschrieben.


EP_WID ist die Länge des gesamten Bearbeitungsbereichs wenn kein Rahmen gesetzt wurde. Wurde ein Rahmen gesetzt, so ist EP_WID die Breite des Fensters, der Bearbeitungsbereich ist um zwei Spalten kürzer. Ist eine Eingabeaufforderung angegeben, so ist der Bearbeitungsbereich um die Länge der Eingabeaufforderung kürzer.
Beispiel:

 TIT 	 DB "Titel",0,"Eingabe: ",0,0
 STRG  DB "Diese Zeile bearbeiten",0
 .
 .
 .
 MOV EP_TIT[0],OFFSET TIT		;Addresse der Titel-
 MOV EP_TIT[2],DS			;Information
 .
 MOV EP_XPOS,2			;Rahmen-Position. Zeile
 MOV EP_YPOS,1			;Rahmen-Position. Spalte
 .
 MOV EP_WID,20			;Länge des Rahmens
 MOV EP_WIND,1			;doppelter Rahmen

Die linke obere Ecke des Rahmens wird sich in der zweiten Zeile und der dritten Spalte befinden. Der Rahmen wird eine Länge von insgesamt 20 Spalten haben (die rechte untere Ecke in der vierten Zeile und der dreiundzwanzigsten Spalte). Die Eingabeaufforderung „Eingabe: “ beginnt in der dritten Zeile und der vierten Spalte, die zu bearbeitende Zeichenkette in der selben (dritten) Zeile, aber in der dreizehnten Spalte.
Somit bleiben nur 10 Spalten für die Darstellung der zu bearbeitenden Zeichekette (im Beispiel wird nur „Diese Zei“ lesbar sein). Wärend der Bearbeitung wird der Inhalt der Zeichenkette innerhalb dieses 10-Spalten-Bereichs hin und her gescrollt.
Um einen möglichst großen Bereich der Zeichenkette anzuzeigen sollte EP_WID erhöht werden. Dabei ist darauf zu achten, dass der rechte Rand des Rahmens nicht über den Bildschirmbereich (Spalte 39) hinausragt. Ist dies nicht zu vermeiden, so muss der Bildschirm in den Systemeinstellungen auf statisch oder dynamisch umgestellt werden, sonst wird der Rahmen falsch dargestellt.


EP_WIND bestimmt ob ein Rahmen verwendet wird, und ob dieser einfach oder doppelt ist. Ist kein Rahmen erwünscht, so ist dieser Wert auf 0FFh zu setzen, für einen einfachen Rahmen ist der Wert 0, und für einen doppelten Rahmen der Wert 1 zu verwenden. Portfolios Anwendungen verwenden immer den doppelten Rahmen, dieser ändert sich beim Beenden der Bearbeitung automatisch zu einen einfachen Rahmen um anzuzeigen, dass die Bearbeitung nicht mehr aktiv ist.
Beispiel:

MOV EP_WIND,0FFh			;kein Rahmen

Wird ein Rahmen verwendet, so werden Überschrift und Eingabeaufforderung aus der angegebenen Adresse eingesetzt. Sind Überschrift oder Eingabeaufforderung nicht erwünscht, so sind sie als leer anzugeben.
Beispiel:

 TIT  DB   "",0,"",0,0
 .
 .
 .
 MOV EP_TIT[0],OFFSET TIT		;Addresse der Titel-
 MOV EP_TIT[2],DS			;Information
 .
 .
 .
 MOV EP_WIND,1			;doppelter Rahmen



EP_RES ist für das BIOS reserviert. Ein Zugriff auf diesen Wert kann verhehrende Folgen haben. Schreiben sie auf keinen Fall in diesen Bereich!


EP_UDEL ist ein Doppelwort-Zeiger auf die Undelete-Routine. Diese muss dafür sorgen, dass gelöschte Zeichen zurückgeholt werden können. Wenn bei der Bearbeitung einer Zeichenkette Zeichen gelöscht werden (z.B. durch Entf. oder die Korrekturtaste), so müssen diese gespeichert werden um später wieder eingefügt werden können. Die internen Anwendungen verwenden dafür die Datei C:\SYSTEM\UNDELETE.DAT. Diese Datei hat eine bestimmte Struktur.
Sie besteht aus mehreren Datenblöcken. Jeder Block besteht aus einer Anzahl Zeichen die mit einem einzelnen Befehl gelöscht wurden. Jeder Block hat folgendes Format:
Daten Länge Richtung Die Daten sind die gelöschten Zeichen (Zeilenumbrüche werden als 0Dh, nicht 0Dh 0Ah, gespeichert), Länge ist die Anzahl der Zeichen im Block und Richtung ist 0 wenn nach links gelöscht wurde (z.B. mit der Korrekturtaste) und 1 wenn nach rechts gelöscht wurde (z.B. mit Entf).

FIXME

Beispielprogramm


Folgendes Beispiel ist ein kleines Programm, dass die Funktionsweise des Zeileneditors veranschaulicht. Es wurde mit Erik Isaacsons Assembler A86 v3.22 auf dem Portfolio assembliert und getestet.
Durch ändern der Werte in der Prozedur INIT_EDLIN lässen sich Darstellung und Verhalten des Zeileneditors verändern.

;EDLIN.COM Zeileneditor der AES
;löscht den Bildschirm, führt Zeilen-Editor aus,
;gibt die bearbeitete Zeichenkette aus und
;wird beendet.
 
DATA_SEG SEGMENT
 
  STRG	  DB "Diese Zeile bearbeiten.",0
  EDBUF   DB 78 DUP (?)			;Bearbeitungspuffer
 
  EP_TARG DW 2 DUP (?)			;Adresse der Zeichenkette
  EP_POS  DW (?)			;Position innnerhalb der Kette
  EP_MAX  DW (?)			;max. Länge der Kette
  EP_XPOS DB (?)			;Cursor-Position. Spalte.
  EP_YPOS DB (?)			;Cursor-Position. Zeile.
  EP_MODE DB (?)			;Zeichenkette löschen?
  EP_HIT  DW (?)			;Pre-Processing
  EP_TIT  DW 2 DUP (?)			;Adresse der Überschrift
  EP_EXIT DW 2 DUP (?)			;Adresse der Liste für Ausstiegstasten
  EP_FN   DW 2 DUP (?)			;Adresse der Routine für Tastaturabfrage
  EP_WID  DB (?)			;max. Länge des Editier-Bereichs
  EP_WIND DB (?)			;Rahmen-Typ (0FFh=keiner,0=einfach,1=doppelt)
  EP_RES  DW 2 DUP (?)			;reserviert! Nicht verändern.
  EP_UDEL DW 2 DUP (?)			;Adressse der Undelete-Routine
 
 
DATA_SEG ENDS
 
CODE_SEG SEGMENT
 
MOV AH,0		;AES initialisieren
INT 61h
 
JMP MAIN		;Sprung zur Haupt-Routine
 
 
;Prozeduren
 
INIT_EDLIN		PROC		;Datenstruktur initialisieren
  MOV AX,OFFSET EDBUF			;Adresse des Bearbeitungspuffers
  MOV EP_TARG[0],AX
  MOV EP_TARG[2],DS
 
  MOV EP_POS,0				;Position innnerhalb der Kette
  MOV EP_MAX,80				;max. Länge der Kette
  MOV EP_XPOS,4				;Position des Eingabebereichs (Rahmen). Spalte.
  MOV EP_YPOS,2				;Position des Eingabebereichs (Rahmen). Zeile.
  MOV EP_MODE,2				;Zeichenkette löschen? (2=nein, 0FFh=ja)
  MOV EP_HIT,0				;Pre-Processing (0=nein, 1=ja)
 
  MOV AX,OFFSET TIT			;Adresse der Überschrift und Eingabeaufforderung
  MOV EP_TIT[0],AX
  MOV EP_TIT[2],CS
 
  MOV AX,OFFSET EXK 			;Adresse der Liste für Ausstiegstasten
  MOV EP_EXIT[0],AX
  MOV EP_EXIT[2],CS
 
  MOV AX,GET_KEY			;Adresse der Routine für Tastaturabfrage
  MOV EP_FN[0],AX
  MOV EP_FN[2],CS
 
  MOV EP_WID,31				;maximale Länge des Bereichs oder der Rahmens
  MOV EP_WIND,1				;Rahmen-Typ (0FFh=keiner,0=einfach,1=doppelt)
 
  MOV AX,UDEL				;Adressse der Undelete-Routine
  MOV EP_UDEL[0],AX
  MOV EP_UDEL[2],CS
 
RET					;Ende der Initialisierung der Datenstruktur
 
 
 
 
INIT_EDBUF		PROC		;Zeichenkette in Puffer kopieren
  MOV DI,0
  MOV SI,0
 IB0:
  MOV AL,STRG[SI]			;Zeichen lesen
  MOV EDBUF[DI],AL			;Zeichen speichern
  CMP AL,0				;Ende der Zeichenkette?
  JE IB1
  INC SI				;nächstes Zeichen
  INC DI
  JMP IB0				;wiederholen
 IB1:					;Ende der Zeichenkette
RET
 
 
GET_KEY			PROC		;Tastaturabfrage
  MOV AH,0				;Taste abfragen
  INT 16h				;Tastatut-Interrupt
  CMP AL,0				;Wenn Tastencode erweitert
  JE GK0				;dann nächstes Byte holen
  MOV AH,0				;Wenn kein Tastencode in AX
RETF					;dann Rückkehr
 GK0:
  MOV AL,AH				;Tastencode nach AL
  MOV AH,1				;AH = 1
RETF					;zurück
 
 
UDEL			PROC		;Undelete-Routine
RETF					;zurück
 
 
ECHO_EDBUF		PROC		;bearbeitete Zeichenkette ausgeben
  MOV AH,2				;Funktion Cursor-Position setzen
  MOV BX,0				;Page Nummer
  MOV DH,5				;Zeile
  MOV DL,5				;Spalte
  INT 10h				;Bildschirm-Interrupt
  MOV SI,0
 EB0:
  MOV DL,EDBUF[SI]			;Zeichen holen
  CMP DL,0				;Ende der Zeichenkette?
  JE EB1				;dann beenden
  MOV AH,2				;Zeichen ausgeben
  INT 21h				;DOS-Interrupt
  INC SI				;nächstes Zeichen
 JMP EB0				;wiederholen
 EB1:					;beenden
RET
 
 
CLR_SCREEN	PROC			;Bildschirm löschen
  MOV AH,0				;Bildschirm-Modus setzen
  MOV AL,7				;Text
  INT 10h				;Bildschirm-Interrupt
RET
 
 
QUIT			PROC		;Programm beenden
 MOV AH,4Ch				;Funktion "beenden"
 MOV AL,0				;Fehlernummer
 INT 21h				;zurück zu DOS
 
 
MAIN:					;Haupt-Routine
  CALL CLR_SCREEN			;Bildschirm löschen
  CALL INIT_EDBUF			;Zeichkette in Puffer lesen
  CALL INIT_EDLIN			;Datenstruktur initialisieren
  MOV SI,OFFSET EP_TARG			;Adresse der Datenstruktur
  MOV AH,1				;Funktion Zeileneditor
  INT 60h				;AES-Interrupt
  CALL ECHO_EDBUF			;Zeichenkette ausgeben
  CALL QUIT				;beenden
END MAIN				;ende der Haupt-Routine
 
 
TIT 	DB "Titel",0,"Eingabe: ",0,0	;Überschrift und Eingabeaufforderung
EXK	DW 000Dh,001Bh,00h		;Liste der Ausstiegstasten (Esc und Eingabetaste)
 
CODE_SEG ENDS


Einige Routinen des Programms könnten durchaus kleiner sein, hier wurde Wert auf die Nachvollziehbarkeit gelegt, der Quellcode hat didaktischen Character und kann durchaus optimiert werden. Die Undelete-Routine fehlt noch.

Wenn man ein wenig mit den Werten in der Prozedur INIT_EDLIN herumspielt merkt man sehr bald, daß es eine gewisse Abhängikgeit zwischen diesen gibt.
Damit man in beim Programmieren keine Überraschungen erlebt sollte man diese gegenseitige Abhängigkeit berücksichtigen und evtl. nur die wichtigsten zu definieren, die anderen vom Programm selbst daraus errechnen lassen.

Wenn der Rahmen aktiviert ist (EP_WIND < 0FFh):
EP_XPOS < 40-EP_WID
EP_YPOS < 6
Bearbeitungsbereich = EP_WID - 2 - Länge der Eingabeaufforderung
rechter Rand des Rahmens ist bei EP_XPOS + EP_WID


Wenn der Rahmen deaktiviert ist (EP_WIND = 0FFh):
EP_XPOS < 40-EP_WID
EP_YPOS < 8
Bearbeitungsbereich = EP_WID


In dem obigen Beispiel fehlt noch eine wichtige Komponente, ohne die nocht nicht wirklich von AES die Rede sein kann. Das Speichern und wiederherstellen des Bildschirminhalts. Dies ist auch für die Verwendung von Menüs sehr wichtig, und wird deshalb auch in dem entsprechenden Abschnitt behandelt.

Menüs werden mit der Funktion 0Fh des Interrupt 60h aufgerufen. Nach erfolgter Auswahl gibt die Funktion die Nummer der gewählten Option zurück. Anders als beim Zeileneditor, werden die Werte für die Menüsteuerung in Registern abgelegt.

;MINIMENU.COM
 
    MOV AH,15				;Menü-Funktion
    MOV BH,0				;Video-Page
    MOV AL,0				;Menütiefe (0:keine Prüfung)
    ADD AL,1				;doppel-Rahmen
    MOV CH,0				;oberste Option
    MOV CL,1				;Cursor-Zeile
    MOV DH,1				;Menü-Position. Zeile.
    MOV DL,5				;Menü-Position. Spalte
    MOV SI,OFFSET MENTXT		;Zeiger auf Menütext
    MOV DI,0FFFFh			;kein Default-Text
    INT 60h
 
    MOV DX,AX				;Rückgabe sichern
    MOV AL,0				;ERRORLEVEL 0
    CMP DX,-1				;Esc gedrückt?
    JE MM0				;Abbruch
    MOV AL,DL				;ERRORLEVEL = 
    ADD AL,DH				;DL+DH = Option
   MM0:
    MOV AH,4Ch				;Programm beenden
    INT 21h				;zurück zu DOS
 
   MENTXT  DB  "Titel",0,"Erstens",0,"Zweitens",0,"Drittens",0,"Viertens",0,0

Im ersten Block wird die Menüfunktion aufgerufen, im zweiten Block wird die Rückkgabe ausgewertet und das Ergebnis als ERRORLEVEL ausgegeben um in einer Batch-Datei ausgelesen zu werden (wenn 0, dann wurde die Escape-Taste gedrückt, wenn nicht, dann ist der ERRORLEVEL die gewählte Oprion).
Nach dem Start kann mann mit den Cursor-Tasten auf und ab scrollen und die Auswahl mit der Eingabe-Taste bestätigen, oder direkt den Anfangsbuchstaben der gewünschten Option tippen und das Programm wird beendet.

Die Register

AH: Funktionsnummer 15 (0Fh)

AL: Bit 1 signalisiert die Art des Rahmens (0 für einfach, 1 für doppelt). Bits 3 bis 7 sind die Menütiefe. Wenn mehr Menü-Optionen vorhanden sind als das Menü Zeilen hat (ohne den Rahmen zu zählen), so ist die gewünschte Menühöhe (inkl. Rahmen) mit acht zu multiplizieren (die Menüfunktion erwartet die Höhenangabe in Bits 3 bis 7). Wenn diese Bits gleich Null sind, so findet keine Tiefenprüfung satt, der Programmierer hat Sorge zu tragen, dass das Menu nicht über den unteren Bildschirmrand hinausragt. Ein Menu, das in der ersten Bildschirmzeile beginnt kann maximal 6 Optionen darstellen.

BH: die Video-Page (normalerweise 0).

CX: Bestimmt wo sich der Cursor zu Beginn befinden soll (meistens die Option die zuletzt ausgewählt wurde. CH bestimmt den Ausschnitt der Liste, das heißt, welche Option in der ersten Menüzeile erscheinen soll. CL bestimmt in welcher Zeile des Menüs der Cursor steht.

DX: Enthält die Bildschirm-Position des Menüs, DH die Zeile und DL die Spalte.

SI: Enthält die Adresse des Menütextes (Überschrift und Optionen).

Der Menutext betseht aus der Überschrift und aller Menü-Optionen, jeweils durch NULL getrennt und am Ende doppelt NULL-terminiert.

ES:DI: Enthält die Adresse des Default-Textes (jede Option kann rechts einen Parameter oder Zustand anzeigen).

Der Default-Text besteht aus durch NULL getrennte Zeichenketten (für jede Option eine), und ist doppelt NULL-terminiert.

Nach Ausführung der Menüfunktion enthält das Register AX das Ergebnis. Ist AX = -1, so hat der Anwender das Menü mit der Ecape-Taste verlassen. Wenn nicht, enthält AH die Optionsnummer die in der obersten Menüzeile stand (von Null an gezählt) und AL die Zeile die im Menü ausgewählt wurde. Die Ordinalzahl innerhalb der Liste erhält man durch die Summe beider Werte.

Bildschirm Wiederherstellen

Das obere Beispiel ist das simpelste. Im realen Einsatz wird man mehr als ein Menü verwenden wollen und das in verschiedenen Ebenen. Leider hat die Menüfunktion keine automatische Bildschirm-Wiederherstellung, so ist die Rückkehr in ein Übergeordnetes Menü nicht sehr schön. Die AES bieten aber Unterstützung um eine solche Wiederherstellung zu programmieren: Funktion 08h (Bildschirm speichern/laden) und Funktion 10h (Fläche berechnen) des Interrupt 60h.

Für das Zwischenspeichern der Bildschirminhalte müssen Puffer angelegt werden. Der größte nötige Puffer ist 320 Bytes lang (der gesamte Bildschirm).

SCRBUF0  DB  320 DUP (?)	;Puffer für Menü-Ebene 0
SCRBUF1  DB  320 DUP (?)	;Puffer für Menü-Ebene 1
.
.
.

Funktion 10h (Fläche berechnen) des Interrupt 60h berechnet die Breite und Tiefe des angegebenen Menüs (inkl. Default-Texte) und liefert die Position der rechten unteren Ecke, ein Wert, der für die Funktion 08h (Bildschirm speichern/laden) benötigt wird.

.
.
.
MENTXT   DB  "Titel",0,"Erstens",0,"Zweitens",0,"Drittens",0,"Viertens",0,0
MENTOP   DW  260					;linke obere Ecke. Zeile, Spalte. 
MENBUT   DW (?)					;rechte untere Ecke. Zeile, Spalte. 			  MENITM   DW (?)					;Anzahl Menü-Optionen
MENSCR   DW (?)					;Größe des benötigten Bildschirmpuffers
;Fläche berechnen
  MOV Ah,10h						;Funktion Fläche berechnen
  MOV DX,MENTOP					;MENTOP nach DX
  MOV SI,MENTXT[0]					;Adresse des Menütextes
  MOV DI,0FFFFh					;kein Default-Text
  INT 60h						;AES-Interrupt
  MOV MENITM,AX					;Anzahl Menü-Optionen
  MOV MENBUT,CX					;untere rechte Ecke
  MOV MENSCR,BX					;Anzahl Bytes (Größe des nötigen Puffers)
;Bildschirmbereich speichern
  MOV AH,8						;Funktion speichern/laden
  MOV AL,0						;speichern
  MOV BH,0						;Video-Page
  MOV SI,SCRBUF0					;Adresse des Puffers
  MOV CX,MENBUT					;rechte untere Ecke
  MOV DX,MENTOP					;linke obere Ecke
  INT 60h						;AES-Interrupt
.
.
.

Nun ist der Inhalt Bidschirmbereichs in dem angegebenen Puffer (SCRBUF0) gespeichert. Die Menüfuntion kann aufgerufen werden und der Bildschirmbereich kann wiederhegstellt werden.

.
.
.
;Bildschirmbereich laden
  MOV AH,8						;Funktion speichern/laden
  MOV AL,2						;laden
  MOV BH,0						;Video-Page
  MOV SI,SCRBUF0					;Adresse des Puffers
  MOV CX,MENBUT					;rechte untere Ecke
  MOV DX,MENTOP					;linke obere Ecke
  INT 60h						;AES-Interrupt

Der ursprüngliche Inhalt des Bildschirmbereichs ist Wiederhergestellt.

Meldungen

Die AES bieten zwei Arten von Meldungen mit unterschiedlichen Eigenschaften. Die Banachrichtigungen (wie z.B. beim Speichern und Laden von Dateien) und die Fehlermeldungen (wie z.B. Teilung durch NULL).

Benachrichtigung

Wird mit der Funktion 12h des Int 60h aufgerufen. Die Benachrichtigung zeigt eine Zeichenkette in doppeltem Rahmen mit Überschrift. Die Message-Funktion erwartet die Adresse des Textes in CS:SI.
Beispiel:

   MOV AH,0			;AES initialisieren
   INT 61h
 
   MOV SI,OFFSET MSG		;Adresse des Textes (CS:SI)
   MOV BH,0			;Page-Nummer
   MOV DH,3			;linke obere Ecke des Rahmens. Spalte.
   MOV DL,2			;linke obere Ecke des Rahmens. Zeile.
   MOV AH,12h			;Funktion Message
   INT 60h			;AES-Interrupt
 
   MOV AH,4Ch			;Programm beenden
   MOV AL,0			;Fehlernummer
   INT 21h
 
   MSG  DB "Nachricht",0,"Dies ist eine AES-Benachrichtigung.",0,0

Der Programmierer muss selber für die Wiederherstellung des Bildschirms sorgen. Siehe dazu den entsprechenden Abschnitt.

Fehlermeldung

Wird mit der Funktion 14h des Int 60h aufgerufen. Die Fehlermeldung zeigt eine Zeichenkette in einem doppelten Rahmen (ohne Überschrift), gibt einen Warnton aus und wartet auf einen Tastendruck. Im Gegensatz zur Benachrichtigung sorgt die Funktion selbst für die Wiederherstellung des Bildschirms.
Beispiel:

   MOV AH,0			;AES initialisieren
   INT 61h
 
   MOV SI,OFFSET MSG		;Adresse des Textes (CS:SI)
   MOV BH,0			;Page-Nummer
   MOV DH,10			;linke obere Ecke des Rahmens. Spalte.
   MOV DL,1			;linke obere Ecke des Rahmens. Zeile.
   MOV AH,14h			;Funktion Message
   INT 60h			;AES-Interrupt
 
   MOV AH,4Ch			;Programm beenden
   MOV AL,0			;Fehlernummer
   INT 21h
 
   MSG  DB "Zeile 1",0,"Zeile 2",0,"Zeile 3",0,0

In diesem Beispiel besteht der Text aus drei, durch NULL getrennte Zeilen.

Meldungen

Die AES bieten zwei Arten von Meldungen mit unterschiedlichen Eigenschaften. Die Banachrichtigungen (wie z.B. beim Speichern und Laden von Dateien) und die Fehlermeldungen (wie z.B. Teilung durch NULL).

Benachrichtigung

Wird mit der Funktion 12h des Int 60h aufgerufen. Die Benachrichtigung zeigt eine Zeichenkette in doppeltem Rahmen mit Überschrift. Die Message-Funktion erwartet die Adresse des Textes in CS:SI.
Beispiel:

   MOV AH,0			;AES initialisieren
   INT 61h
 
   MOV SI,OFFSET MSG		;Adresse des Textes (CS:SI)
   MOV BH,0			;Page-Nummer
   MOV DH,3			;linke obere Ecke des Rahmens. Spalte.
   MOV DL,2			;linke obere Ecke des Rahmens. Zeile.
   MOV AH,12h			;Funktion Message
   INT 60h			;AES-Interrupt
 
   MOV AH,4Ch			;Programm beenden
   MOV AL,0			;Fehlernummer
   INT 21h
 
   MSG  DB "Nachricht",0,"Dies ist eine AES-Benachrichtigung.",0,0

Der Programmierer muss selber für die Wiederherstellung des Bildschirms sorgen. Siehe dazu den entsprechenden Abschnitt.

Fehlermeldung

Wird mit der Funktion 14h des Int 60h aufgerufen. Die Fehlermeldung zeigt eine Zeichenkette in einem doppelten Rahmen (ohne Überschrift), gibt einen Warnton aus und wartet auf einen Tastendruck. Im Gegensatz zur Benachrichtigung sorgt die Funktion selbst für die Wiederherstellung des Bildschirms.
Beispiel:

   MOV AH,0			;AES initialisieren
   INT 61h
 
   MOV SI,OFFSET MSG		;Adresse des Textes (CS:SI)
   MOV BH,0			;Page-Nummer
   MOV DH,10			;linke obere Ecke des Rahmens. Spalte.
   MOV DL,1			;linke obere Ecke des Rahmens. Zeile.
   MOV AH,14h			;Funktion Message
   INT 60h			;AES-Interrupt
 
   MOV AH,4Ch			;Programm beenden
   MOV AL,0			;Fehlernummer
   INT 21h
 
   MSG  DB "Zeile 1",0,"Zeile 2",0,"Zeile 3",0,0

In diesem Beispiel besteht der Text aus drei, durch NULL getrennte Zeilen. Fehlermeldungen haben keine Überschrift.

Wählton

Der Wählton wird mit der Funktion 17h des INT 61h aufgerufen, die Adresse der Wahlfolge wird in DS:SI erwartet. Mit Hilfe der Funktion 18h kann auch die Länge des DTMF-Tons bestimmt werden um die Wählgeschwindigkeit zu beeinflussen.
Beispiel:

;AESDIAL.COM
TEL   DB  "0123456789ABCD*#",0,0	;Wahlfolge
 
MOV AH,0				;AES initialisieren
INT 61h
 
MOV AH,18h				;Funktion Mute-Sates
MOV AL,09				;DTMF-Länge setzen
MOV DX,19000				;DX zwischen 0 und 65535, 29411 typisch
INT 61h
 
MOV SI,OFFSET TEL			;Adresse der Wahlfolge
MOV CX,16				;Länge der Wahlfolge
MOV AH,17h				;Funktion DTMF ausgeben
INT 61h
 
MOV AH,4Ch				;Programm beenden
MOV AL,0				;Fehelernummer
INT 21h

AESDIAL.COM ist 47 Bytes groß. Man könnte sich die wichtigsten Telefonnummern als Programme ablegen und nach Namen in der DOS-Eingabeauforderung aufrufen.

software/diy/assembler/aes.1196898676.txt.gz · Zuletzt geändert: 06/12/2007 00:12 (Externe Bearbeitung)