software:diy:assembler:aes
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende ÜberarbeitungLetzte ÜberarbeitungBeide Seiten der Revision | ||
software:diy:assembler:aes [12/12/2007 23:12] – ergänzt. uxt | software:diy:assembler:aes [13/12/2007 00:12] – typo uxt | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
- | ====== 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, | ||
- | 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\\ | ||
- | * Meldungen\\ | ||
- | * Wählton\\ | ||
- | * Melodie-Töne\\ | ||
- | * 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, | ||
- | <code asm> | ||
- | EP_TARG DW 2 DUP (? | ||
- | EP_POS | ||
- | EP_MAX | ||
- | EP_XPOS DB (? | ||
- | EP_YPOS DB (? | ||
- | EP_MODE DB (? | ||
- | EP_HIT | ||
- | EP_TIT | ||
- | EP_EXIT DW 2 DUP (? | ||
- | EP_FN DW 2 DUP (? | ||
- | EP_WID | ||
- | EP_WIND DB (? | ||
- | EP_RES | ||
- | EP_UDEL DW 2 DUP (? | ||
- | </ | ||
- | \\ | ||
- | |||
- | 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", | ||
- | . | ||
- | . | ||
- | . | ||
- | MOV EP_TARG[0], | ||
- | MOV EP_TARG[2], | ||
- | 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 " | ||
- | \\ | ||
- | \\ | ||
- | **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, | ||
- | 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, | ||
- | \\ | ||
- | \\ | ||
- | **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, | ||
- | Beispiel:\\ | ||
- | TIT DB " | ||
- | . | ||
- | . | ||
- | . | ||
- | MOV EP_TIT[0], | ||
- | MOV EP_TIT[2], | ||
- | 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 " | ||
- | \\ | ||
- | \\ | ||
- | **EP_EXIT** ist ein Doppelwort-Zeiger auf eine Liste von Tasten-Codes, | ||
- | Beispiel:\\ | ||
- | EXIT_KEYS | ||
- | . | ||
- | . | ||
- | . | ||
- | MOV EP_EXIT[0], | ||
- | MOV EP_EXIT[2], | ||
- | 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 | ||
- | . | ||
- | . | ||
- | . | ||
- | 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 " | ||
- | | ||
- | . | ||
- | . | ||
- | . | ||
- | MOV EP_TIT[0], | ||
- | MOV EP_TIT[2], | ||
- | . | ||
- | MOV EP_XPOS, | ||
- | MOV EP_YPOS, | ||
- | . | ||
- | MOV EP_WID, | ||
- | MOV EP_WIND, | ||
- | 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 " | ||
- | 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, | ||
- | 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:\\ | ||
- | | ||
- | . | ||
- | . | ||
- | . | ||
- | MOV EP_TIT[0], | ||
- | MOV EP_TIT[2], | ||
- | . | ||
- | . | ||
- | . | ||
- | MOV EP_WIND, | ||
- | \\ | ||
- | \\ | ||
- | **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), | ||
- | 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), | ||
- | \\ | ||
- | 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. | ||
- | \\ | ||
- | \\ | ||
- | <code asm> | ||
- | ;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.", | ||
- | EDBUF DB 78 DUP (? | ||
- | |||
- | EP_TARG DW 2 DUP (? | ||
- | EP_POS | ||
- | EP_MAX | ||
- | EP_XPOS DB (? | ||
- | EP_YPOS DB (? | ||
- | EP_MODE DB (? | ||
- | EP_HIT | ||
- | EP_TIT | ||
- | EP_EXIT DW 2 DUP (? | ||
- | EP_FN DW 2 DUP (? | ||
- | EP_WID | ||
- | EP_WIND DB (? | ||
- | EP_RES | ||
- | EP_UDEL DW 2 DUP (? | ||
- | |||
- | |||
- | DATA_SEG ENDS | ||
- | |||
- | CODE_SEG SEGMENT | ||
- | |||
- | MOV AH,0 ;AES initialisieren | ||
- | INT 61h | ||
- | |||
- | JMP MAIN ; | ||
- | |||
- | |||
- | ;Prozeduren | ||
- | |||
- | INIT_EDLIN PROC ; | ||
- | MOV AX,OFFSET EDBUF ; | ||
- | MOV EP_TARG[0], | ||
- | MOV EP_TARG[2], | ||
- | |||
- | MOV EP_POS, | ||
- | MOV EP_MAX, | ||
- | MOV EP_XPOS, | ||
- | MOV EP_YPOS, | ||
- | MOV EP_MODE, | ||
- | MOV EP_HIT, | ||
- | |||
- | MOV AX,OFFSET TIT ; | ||
- | MOV EP_TIT[0], | ||
- | MOV EP_TIT[2], | ||
- | |||
- | MOV AX,OFFSET EXK ;Adresse der Liste für Ausstiegstasten | ||
- | MOV EP_EXIT[0], | ||
- | MOV EP_EXIT[2], | ||
- | |||
- | MOV AX, | ||
- | MOV EP_FN[0],AX | ||
- | MOV EP_FN[2],CS | ||
- | |||
- | MOV EP_WID, | ||
- | MOV EP_WIND, | ||
- | |||
- | MOV AX, | ||
- | MOV EP_UDEL[0], | ||
- | MOV EP_UDEL[2], | ||
- | |||
- | RET ; | ||
- | |||
- | |||
- | |||
- | |||
- | INIT_EDBUF PROC ; | ||
- | MOV DI,0 | ||
- | MOV SI,0 | ||
- | IB0: | ||
- | MOV AL, | ||
- | MOV EDBUF[DI], | ||
- | CMP AL, | ||
- | JE IB1 | ||
- | INC SI ; | ||
- | INC DI | ||
- | JMP IB0 ; | ||
- | | ||
- | RET | ||
- | |||
- | |||
- | GET_KEY PROC ; | ||
- | MOV AH, | ||
- | INT 16h ; | ||
- | CMP AL, | ||
- | JE GK0 ; | ||
- | MOV AH, | ||
- | RETF ; | ||
- | GK0: | ||
- | MOV AL, | ||
- | MOV AH,1 ;AH = 1 | ||
- | RETF ; | ||
- | |||
- | |||
- | UDEL PROC ; | ||
- | RETF ; | ||
- | |||
- | |||
- | ECHO_EDBUF PROC ; | ||
- | MOV AH, | ||
- | MOV BX, | ||
- | MOV DH, | ||
- | MOV DL, | ||
- | INT 10h ; | ||
- | MOV SI,0 | ||
- | EB0: | ||
- | MOV DL, | ||
- | CMP DL, | ||
- | JE EB1 ; | ||
- | MOV AH, | ||
- | INT 21h ; | ||
- | INC SI ; | ||
- | JMP EB0 ; | ||
- | | ||
- | RET | ||
- | |||
- | |||
- | CLR_SCREEN PROC ; | ||
- | MOV AH, | ||
- | MOV AL, | ||
- | INT 10h ; | ||
- | RET | ||
- | |||
- | |||
- | QUIT PROC ; | ||
- | MOV AH, | ||
- | MOV AL, | ||
- | INT 21h ; | ||
- | |||
- | |||
- | MAIN: | ||
- | CALL CLR_SCREEN ; | ||
- | CALL INIT_EDBUF ; | ||
- | CALL INIT_EDLIN ; | ||
- | MOV SI,OFFSET EP_TARG ; | ||
- | MOV AH, | ||
- | INT 60h ; | ||
- | CALL ECHO_EDBUF ; | ||
- | CALL QUIT ; | ||
- | END MAIN ; | ||
- | |||
- | |||
- | TIT DB " | ||
- | EXK DW 000Dh, | ||
- | |||
- | 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 ===== | ||
- | 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, | ||
- | <code asm> | ||
- | ; | ||
- | |||
- | MOV AH, | ||
- | MOV BH, | ||
- | MOV AL, | ||
- | ADD AL, | ||
- | MOV CH, | ||
- | MOV CL, | ||
- | MOV DH, | ||
- | MOV DL, | ||
- | MOV SI,OFFSET MENTXT ; | ||
- | MOV DI, | ||
- | INT 60h | ||
- | |||
- | MOV DX, | ||
- | MOV AL, | ||
- | CMP DX, | ||
- | JE MM0 ; | ||
- | MOV AL, | ||
- | ADD AL, | ||
- | MM0: | ||
- | MOV AH, | ||
- | INT 21h ; | ||
- | |||
- | | ||
- | </ | ||
- | |||
- | 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, | ||
- | |||
- | ==== 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, | ||
- | |||
- | **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, | ||
- | \\ | ||
- | 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 | ||
- | SCRBUF1 | ||
- | . | ||
- | . | ||
- | . | ||
- | |||
- | 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/ | ||
- | |||
- | . | ||
- | . | ||
- | . | ||
- | MENTXT | ||
- | MENTOP | ||
- | MENBUT | ||
- | MENITM | ||
- | MENSCR | ||
- | |||
- | ;Fläche berechnen | ||
- | MOV AH, | ||
- | MOV DX, | ||
- | MOV SI,OFFSET MENTXT ; | ||
- | MOV DI, | ||
- | INT 60h ; | ||
- | MOV MENITM, | ||
- | MOV MENBUT, | ||
- | MOV MENSCR, | ||
- | |||
- | ; | ||
- | MOV AH, | ||
- | MOV AL, | ||
- | MOV BH, | ||
- | MOV SI, | ||
- | MOV CX, | ||
- | MOV DX, | ||
- | INT 60h ; | ||
- | . | ||
- | . | ||
- | . | ||
- | |||
- | Nun ist der Inhalt des Bidschirmbereichs in dem angegebenen Puffer (SCRBUF0) gespeichert. Die Menüfunktion kann aufgerufen werden und der Bildschirmbereich kann wiederhegstellt werden.\\ | ||
- | |||
- | . | ||
- | . | ||
- | . | ||
- | ; | ||
- | MOV AH, | ||
- | MOV AL, | ||
- | MOV BH, | ||
- | MOV SI, | ||
- | MOV CX, | ||
- | MOV DX, | ||
- | INT 60h ; | ||
- | |||
- | 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:\\ | ||
- | <code asm> | ||
- | MOV AH,0 ;AES initialisieren | ||
- | INT 61h | ||
- | |||
- | MOV SI,OFFSET MSG ; | ||
- | MOV BH, | ||
- | MOV DH, | ||
- | MOV DL, | ||
- | MOV AH, | ||
- | INT 60h ; | ||
- | |||
- | MOV AH, | ||
- | MOV AL, | ||
- | INT 21h | ||
- | |||
- | | ||
- | </ | ||
- | 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), | ||
- | Beispiel:\\ | ||
- | <code asm> | ||
- | MOV AH,0 ;AES initialisieren | ||
- | INT 61h | ||
- | |||
- | MOV SI,OFFSET MSG ; | ||
- | MOV BH, | ||
- | MOV DH, | ||
- | MOV DL, | ||
- | MOV AH, | ||
- | INT 60h ; | ||
- | |||
- | MOV AH, | ||
- | MOV AL, | ||
- | INT 21h | ||
- | |||
- | | ||
- | </ | ||
- | |||
- | 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:\\ | ||
- | <code asm> | ||
- | ; | ||
- | TEL | ||
- | |||
- | MOV AH, | ||
- | INT 61h | ||
- | |||
- | MOV AH, | ||
- | MOV AL, | ||
- | MOV DX, | ||
- | INT 61h | ||
- | |||
- | MOV SI,OFFSET TEL ; | ||
- | MOV CX, | ||
- | MOV AH, | ||
- | INT 61h | ||
- | |||
- | MOV AH, | ||
- | MOV AL, | ||
- | 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.\\ | ||
- | \\ | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | ===== Melodie-Töne ===== | ||
- | |||
- | Die Funktion zur Ausgabe von Melodytönen wird durch den Interrupt 61H Fn 16H aufgerufen. | ||
- | Der Code für den zu erzeugenden Ton ist im Register DL anzugeben (siehe Tabelle) und die Länge in 10ms-Schritten im Register CX.\\ | ||
- | Die Funktion arbeitet monophon, es kann nur eine Note auf einmal ausgegeben werden, Zweiklang oder Dreiklang sind nicht möglich. Die Tonleiter umfasst leider nur knapp über 2 Oktaven (25 Noten). Die kürzeste spielbare Note ist 10ms lang.\\ | ||
- | \\ | ||
- | Im folgenden Beispiel werden die Ton-Codes und deren Dauer in der Variable MLDY gespeichert. Das Programm übergibt diese Werte nach und nach der Fn 16H bis die NULL am Ende der Variable das Ende der Kette signalisiert.\\ | ||
- | \\ | ||
- | <code asm> | ||
- | ;Die Hex-Zahlen stehen für die Ton-Codes, gefolgt von | ||
- | ;den Längen der Noten (mal 10ms) in Dezimal-Zahlen. | ||
- | | ||
- | MLDY | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | MOV AH,0 ;AES initialisieren | ||
- | INT 61h | ||
- | | ||
- | MOV CX, | ||
- | MOV SI, | ||
- | MM0: | ||
- | MOV DL, | ||
- | CMP DL, | ||
- | JE MM9 ;dann Ende | ||
- | INC SI ; | ||
- | MOV CL, | ||
- | MOV AH, | ||
- | INT 61h ; | ||
- | INC SI ; | ||
- | JMP MM0 ; | ||
- | MM9: | ||
- | MOV AH, | ||
- | MOV AL, | ||
- | INT 21h ; | ||
- | </ | ||
- | |||
- | ==== Ton-Codes ==== | ||
- | Hier die Tabelle der Ton-Codes mit den entsprehenden Noten:\\ | ||
- | Ton-Code | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | |||
- | Am Ende der zweiten und dritten Zeile der Melodie-Folge wird der Ton-Code 80h angegeben, er ist nicht dokumentiert, | ||
- | \\ | ||
- | ==== Abspielgeshwindigkeit ==== | ||
- | Um die Abspielgeschwindigkeit zu ändern, müsste man in obigen Beispiel alle Längenangaben in der Variable MLDY austauschen. Um dies zu verhindern, sollte die tatsächliche Länge erst zur Laufzeit ermittelt werden, in der Variable stünden dann nur die Längenverhältnisse in Bezug auf eine Konstante. Hier erweist sich die Angabe in 10ms-Schritten als etwas ungünstig, wenn man eine hohe Zeitauflösung braucht (16tel, 32stel oder gar 64stel Noten). Die Zahlen in der Tabelle sind Längencodes, | ||
- | |||
- | | ||
- | | ||
- | | ||
- | | ||
- | 93.75 | ||
- | 75 320 160 | ||
- | 62.5 348 192 | ||
- | 53, | ||
- | 46, | ||
- | |||
- | 375 BPM ist rasend schnell, 187,5 BPM geht gerade noch. Um die 120 BPM haben wir aber nur 125 BPM und 93 BPM. Das sind recht extreme Geschwindigkeitsunterschiede. Kann man auf 64stel Noten verzichten, so wird es etwas besser:\\ | ||
- | |||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | 93,75 | ||
- | 83,33 | ||
- | 75 320 160 | ||
- | 68,18 | ||
- | 62.5 384 192 | ||
- | 57, | ||
- | 53, | ||
- | 50 480 240 120 60 | ||
- | |||
- | Man betrachte den Bereich um die 120 BPM: 125, 107, 94 ... Noch mehr Spielraum erreicht man nur, wenn man die 32stel Noten auch noch weg lässt: | ||
- | |||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | 93,75 | ||
- | 88, | ||
- | 83,33 | ||
- | 78, | ||
- | 75 320 160 | ||
- | 71, | ||
- | 68,18 | ||
- | 65, | ||
- | 62.5 384 192 | ||
- | 60 400 200 100 50 25 | ||
- | 57, | ||
- | 55.55 | ||
- | |||
- | Nun hat man um die 120 BPM herum mehr Werte: 125, 115, 107, 100, und 94. Simple Melodien wie "Alle meine Entchen", | ||
- | |||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | | ||
- | 96,77 | ||
- | 93,75 | ||
- | 90.9090 | ||
- | 88, | ||
- | 85, | ||
- | 83,33 | ||
- | 81,081081 296 148 | ||
- | 78, | ||
- | 76, | ||
- | 75 320 160 | ||
- | 73, | ||
- | 71, | ||
- | |||
- | 125, 120, 115, 111, 107, 103, 100, 97 und 94 BPM.\\ | ||
- | |||
- | Beinhaltet eine Melodie Triplets, ist darauf zu achten, dass die Viertel-Noten einen Längencode enthalten der auch durch drei teilbar ist. Dies engt die Verfügbarkeit an Abspielgeschwindigkeiten wieder ein.\\ | ||
- | |||
- | Vor dem Abspielen oder Programmieren einer Melodie, sollte man erst festlegen welche Auflösung man braucht (16tel, 32stel oder 64stel), dann alle Längenwerte als Vielfaches dieser kleinsten Einheit errechnen.\\ | ||
- | |||
- | ==== Undokumentierte Ton-Codes ==== | ||
software/diy/assembler/aes.txt · Zuletzt geändert: 13/12/2007 00:12 (Externe Bearbeitung)