| 3.2 Das Monitorprogramm |  | Lösungsvorschläge zu den Selbsttestaufgaben |

P3/1

## Lösungsvorschläge zu den Praktischen Übungen

Zu P3.1-1:

1. Es ist zu sehen, wie nach Betätigen der Taste 'C' das Monitorprogramm zunächst die Speicherzellen $00-$FF initialisiert. Danach wird mit Hilfe eines Datenpuffers in den Zellen $80-$90 die Anzeige aufgebaut. Jede Betätigung einer weiteren Funktionstaste zeigt den wiederholten Zugriff auf diesen Pufferbereich.

2. Das Programm realisiert drei Hexadezimalzähler in den Akkumulatoren A und B sowie der Speicherzelle $00. Diese werden im Hauptprogramm (HP) zunächst initialisiert und dann in HP sowie zwei ineinander geschachtelten Unterprogrammen (SUB1,SUB2) aufwärtsgezählt. Vor jedem Unterprogrammaufruf wird der entsprechende Zählerzustand auf dem Stack abgelegt und nach der Rückkehr aus dem Unterprogramm von dort wieder geladen. Auf der tiefsten Schachtelungstiefe wird in einem weiteren Unterprogramm (SUB3) eine Zeitverzögerung mit der Routine DLY1MS erzeugt (Y=$0040=64 ms). (In DLY1MS wird der eingegebene Verzögerungswert zunächst auf dem Stack gerettet. RA: Rücksprung-Adressen.)

Adresse | OpCode | Mnemocode | Bemerkung
--- | --- | --- | ---
1 | ; Stack -Beobachtung |  |  |
2 |  | DLY1MS |  | EQU | $F160 | ; Verzögerungsroutine
3 |  |  |  |  |  |
4 | 0400 |  |  | ORG | $0400 |
5 | 0400 | CC 10 20 | HP | LDD | #$1020 | ; Zähler Z1 in Akku A, Z2 in B
6 | 0403 | 0F 00 |  | CLR | $00 | ; Zähler Z3 in $00
7 | 0405 | 4C | L | INCA |  | ; Z1 inkrementieren
8 | 0406 | 34 02 |  | PSHS | A | ; Z1 auf den Stack
9 | 0408 | BD 04 20 |  | JSR | SUB1 |
10 | 040B | 35 02 | RA1 | PULS | A | ; Z1 vom Stack
11 | 040D | 20 F6 |  | BRA | L | ; Endlosschleife
12 |  |  |  |  |  |
13 | 0420 |  |  | ORG | $0420 |
14 | 0420 | 5C | SUB1 | INCB |  | ; Z2 inkrementieren
15 | 0421 | 34 04 |  | PSHS | B | ; Z2 auf den Stack
16 | 0423 | BD 04 40 |  | JSR | SUB2 |
17 | 0426 | 35 04 | RA2 | PULS | B | ; Z2 vom Stack
18 | 0428 | 39 |  | RTS |  | ; Rücksprung
19 |  |  |  |  |  |
20 | 0440 |  |  | ORG | $0440 |
21 | 0440 | 0C 00 | SUB2 | INC | $00 | ; Z3 inkrementieren
22 | 0442 | 96 00 |  | LDA | $00 | ; Z3 nach Accu A
23 | 0444 | 34 02 |  | PSHS | A | ; Z3 auf den Stack
24 | 0446 | BD 04 60 |  | JSR | SUB3 |
25 | 0449 | 35 02 | RA3 | PULS | A | ; Z3 vom Stack

P3/2

26 | 044B | 39 |  | RTS |  | ; Rücksprung
27 |  |  |  |  |  |
28 | 0460 |  |  | ORG | $0460 |
29 | 0460 | 10 8E 00 40 | SUB3 | LDY | #$0040 | ; Verzögerungswert Yd
30 | 0464 | BD F1 60 |  | JSR | DLY1MS | ; Verzögerungsroutine
31 | 0467 | 39 | RA4 | RTS |  | ; Rücksprung

Die Beobachtung des Stack-Bereichs zeigt die folgende Speicherzellenbelegung:

Adresse |  |
YdH | YdL
| RA4 | RA3H
1FF0 |
FF | 88 | Z4 | 00 |  | 40 | 04 | 67 | 04
1FF8 |
49 | Z3 | 04 | 26 |  | Z2 | 04 | 0B | Z1
RA3L |  | RA2 |  | RA1 |

Zu P3.1-2:

Der Adreßbereich $1040 -$1047 wird in der folgenden Routine zum Anzeige-Puffer gemacht, indem das X-Register auf den Wert $1040 gesetzt wird. Dieser Puffer wird zunächst mit der Routine CLRBUF (s. Abschnitt 1.2.2) "gelöscht". Danach wird er byteweise unter Beachtung etwaiger Überträge ins nächste Byte inkrementiert. Mit der Routine SHOWDBUF wird nach jeder Erhöhung der Puffer in die Anzeige übertragen.

Adresse | OpCode | Mnemocode | Bemerkung
--- | --- | --- | ---
0400 | 8E 10 40 |  | LDX | #$1040 | ; X setzen
0403 | BD F1 30 |  | JSR | CLRDBUF | ; Löschen des Puffers
0406 | 86 00 | L: | LDA | #0 | ; Bytezähler initialisieren
0408 | 6C 86 | M: | INC | A,X | ; Byte inkrementieren
040A | 26 05 |  | BNE | N | ; zur Anzeigeroutine
040C | 4C |  | INCA |  | ; Bytezähler inkrementieren
040D | 81 08 |  | CMPA | #8 | ; letztes Byte ?
040F | 26 F7 |  | BNE | M | ; nächstes Byte
0411 | BD F1 33 | N: | JSR | SHOWDBUF | ; Anzeigeroutine
0414 | 10 8E 00 01 |  | LDY | #1 | ; Y mit 1 ms laden (1 kHz)
0418 | BD F1 60 |  | JSR | DLY1MS | ; Verzögerung
041B | 7E 04 06 |  | JMP | L |

P3/3

Zu P3.1-3:

Adresse | Opcode | Mnemocode | Bemerkung
--- | --- | --- | ---
0400 | BD F1 10 |  | JSR | CLRDISP | ; Löschen der Anzeige
0403 | 8E F0 10 |  | LDX | #$F010 | ; X initialisieren
0406 | 86 07 | N: | LDA | #7 | ; Spaltenzähler initialisieren
0408 | E6 86 |  | LDB | A,X | ; Spaltenwert nach B bringen
040A | EA 86 | M: | ORB | A,X | ; Spalten "verodern"
040C | C4 0F |  | ANDB | #$F | ; Bits 7-4 maskieren
040E | F7 F0 20 |  | STB | $F020 | ; in die Anzeige bringen
0411 | 4A |  | DECA |  | ; nächste Spalte
0412 | 2A F6 |  | BPL | M | ; falls nicht letzte Spalte
0414 | 2B F0 |  | BMI | N | ; falls letzte Spalte

Zu P3.2-1:

Auf das Flußdiagranm der Routine können wir in diesem Fall verzichten,da wir uns an der Interpreterschleife nach Bild 3.2-2 orientieren. Das Assemblerlisting sieht dann so aus:

Adresse | OpCode | Mnemocode | Bemerkung
--- | --- | --- | ---
; | Kommandointerpreter |  |
1800 |  |  | ORG | $1800 |
1800 | 8E 00 02 | KOM: | LDX | #2 | ; Anzeige im Adreßfeld
1803 | BD F1 56 |  | JSR | SH0WADR | ; Kommandoeingabe
1806 | C1 80 |  | CMPB | #$80 | ; letzte Taste = "+"?
1808 | 26 F9 |  | BNE | -7 | ; sonst neues Kommando
180A | 8E 18 30 |  | LDX | #KOMTAB | ; Beginn der Sprungtabelle
180D | CC FF FF |  | LDD | #$FFFF | ; Zeichen für Tabellenende
1810 | 10 AC 81 NAECHST: | CMPY | ,X + + | ; Vergleich Befehl mit Tabelle
1813 | 27 12 |  | BEQ | GEFUNDEN | ; falls gleich, gefunden
1815 | 30 02 |  | LEAX | 2,X | ; nächste Eintragung
1817 | 10 A3 84 |  | CMPD | ,X | ; Tabellenende erreicht?
181A | 26 F4 |  | BNE | NAECHST | ; sonst weitertesten
181C | 8E 00 00 |  | LDX | #0 | ; im Datenfeld
181F | CC 00 5B |  | LDD | #$5B | ; " ?"
1822 | BD F1 16 |  | JSR | SHOWD | ; ausgeben
1825 | 20 DC |  | BRA | KOM | ; zur Kommandoeingabe
1827 | AD 94 GEFUNDEN: | JSR | [,X] | ; Sprung zur Routine
1829 | BD F1 10 |  | JSR | CLRDISP | ; Anzeige löschen
182C | 20 D5 |  | BRA | KOM | ; zur Kommandoeingabe
1830 |  |  | ORG | $1830 |
1830 | 41 44 KOMTAB: | FDB | 'AD' | ; ASCII-Code des Bezeichners
1832 | E3 B0 |  | FDB | ADDRESS | ; Startadresse der Routine

P3/4

1834 | 44 41 |  | FDB | 'DA' | ;
1836 | E3 F0 |  | FDB | DATEN | ;
1838 | 52 45 |  | FDB | 'RE' | ;
183A | E5 3C |  | FDB | REGIST | ;
183C | 47 4F |  | FDB | 'GO' | ;
183E | E4 30 |  | FDB | GO | ;
1840 | 53 41 |  | FDB | 'SA' | ; für jede Routine:
1842 | E9 00 |  | FDB | SAVE | ;
1844 | 4C 4F |  | FDB | 'LO' | ; Bezeichner
1846 | EA 00 |  | FDB | LOAD | ; Startadresse
1848 | 54 52 |  | FDB | TR' | ;
184A | EC A0 |  | FDB | TRACE | ;
184C | 49 4E |  | FDB | 'IN' | ;
184E | EC 0E |  | FDB | INSERT | ;
1850 | 44 45 |  | FDB | 'DE' | ;
1852 | EC 36 |  | FDB | DELETE | ;
1854 | 44 55 |  | FDB | 'DU' | ;
1856 | EC 5B |  | FDB | DUMP | ;
1858 | FF FF |  | FDB | $FFFF | ; Ende der Sprungtabelle

Der wesentliche Unterschied zwischen beiden Routinen besteht in der Ausführung der Tabelle, die hier sowohl die Bezeichner der Monitorroutinen als auch deren Startadressen aufnehmen muß.

Zu P3.2-2:

1. P3/5

2. Routine INDATA Eingaberegister: Ausgaberegister: A: Datum, B:Funktionstaste Funktion: Liest die Tastatur und packt die beiden zuletzt eingegebenen Hex-Zeichen nach A. Die Routine wird durch eine beliebige Funktionstaste verlassen, deren Code in B zur Verfügung steht. Initialisierung von A mit $00.

   Adresse | OpCode | Mnemocode | Bemerkung
   --- | --- | --- | ---
   F3B6 |  |  | ORG | $F3B6 |
   F3B6 | 4F |  | CLRA |  | ; Initialisierung des Datums
   F3B7 | 8D DC | L: | JSR | HALTKEY | ; auf eine Taste warten
   F3B9 | 2A 01 |  | BPL | W | ; falls Hexadezimalziffer
   F3BB | 39 |  | RTS |  | ; zurück mit Funktionstastencode
   F3BC | 34 04 | W: | PSHS | B | ; Ziffer auf den Stack retten
   F3BE | 48 |  | LSLA |  |
   F3BF | 48 |  | LSLA |  | ; Zahl um eine Ziffer
   F3C0 | 48 |  | LSLA |  | ; nach links schieben
   F3C1 | 48 |  | LSLA |  |
   F3C2 | AA E0 |  | ORA | ,S+ | ; neue Ziffer einfügen
   F3C4 | 20 F1 |  | BRA | L | ; nächste Taste

P3/6

Zu P3.2-3:

1. Die tatsächliche Startadresse ist zu ermitteln, indem Sie in der Sprungtabelle für die Hilfsroutinen bei SHOWADR nachsehen. Dort steht der Befehl "JMP $F3FF", die Startadresse steht also in den Speicherstellen SHOWADR+1 und SHOWADR+2. Da der erste Befehl der Routine,`"LDY #0" (hexadezimal: 10 8E 00 00), nicht ausgeführt werden soll, muß zu der Startadresse vier addiert werden. Es ergibt sich die absolute Sprungadresse $F403.
   Der Sprungbefehl müßte richtig JMP [SHOWADR+1]+4 lauten. Ein 6809-Assembler kann diesen Ausdruck aber nicht verarbeiten, da der Prozessor diese Adressierung nicht kennt. Der Assembler seinerseits kann die absolute Adresse nicht errechnen, da der Inhalt der angegebenen Adresse SHOWADR+1 bei der Assemblierung nicht unbedingt bekannt sein muß und außerdem - falls es sich um Speicherzellen im RAM handelt - zur Laufzeit verändert sein könnte. Daher ist der Umweg über das U-Register zur Berechnung der Startadresse notwendig. Alternativ könnte man die Adresse "zu Fuß" berechnen (siehe oben) und den Sprung mit einer absoluten Adresse versehen: JMP >$F4E4.

2. Folgende Anpassungen der Routine sind notwendig:

   - Der Wert für ADR muß $75 sein, da die anderen Monitorroutinen zur Speicherbearbeitung auch auf diese Adresse zugreifen.

   - Da der Monitor vor dem Sprung in die Routine keine Rücksprungadresse in die Interpreterschleife auf dem Stack ablegt, muß sie nicht mit RTS, sondern mit JMP $E325 abgeschlossen werden. Hier beginnt die Interpreterschleife des Monitors mit der Tastaturabfrage.

   - Der Wert in den Speicherstellen $51, $52, die die Startadresse für die ADDRESS-Routine enthalten, muß gegen die Startadresse Ihrer Routine ausgetauscht werden.

   Sie werden feststellen, daß Sie zur Anwahl der nächsten Monitorfunktion die entsprechende Funktionstaste zweimal betätigen müssen. Das ist notwendig, weil die Tastaturabfrage des Monitors andere Tastencodes liefert als die HALTKEY-Routine.

3. ; Routine ADDRESS: Adresse editieren
   ; Ausgabe der Kennung und Holen der Adresse
   1075 |  | ADR | EQU | $75 |
   ; |  |  | ORG | $1000 |
   1000 | 34 33 | ADDRESS: | PSHS | A,X,Y,CC | ; Register retten
   1002 | BD F1 10 |  | JSR | CLRDISP | ; Anzeige löschen
   1005 | CC 77 5E |  | LDD | #$775E | ; 7-Segmentcode für "Ad"
   1008 | 8E 00 06 |  | LDX | #$6 | ; im Operationsfeld
   100B | BD F1 16 |  | JSR | SHOWD | ; anzeigen
   100E | 10 9E 75 |  | LDY | <ADR | ; zu editierende Adresse holen
   | ; das Zeichen "<" kennzeichnet die DP-Register-Adressierung
   | ; Adresse editieren
   1011 | E6 A4 | W: | LDB | ,Y | ; zugehöriges Datum in Akku B
   1013 | 8E 00 00 |  | LDX | #0 | ; im Datenfeld
   1016 | BD F1 20 |  | JSR | SHOWB7SG | ; anzeigen
   1019 | 8E 00 02 |  | LDX | #2 | ; Anzeige im Adreßfeld
   101C | 12 |  | NOP |
   101D | BE F1 57 |  | LDU | SHOWADR+1 | ; Startadresse aus Sprungtabelle.
   1020 | AD 64 |  | JSR | 4,U | ;Aufruf ohne Löschen von Y
   | ; Ergebnis von SHOWADR interpretieren
   1022 | C1 81 |  | CMPB | #$81 | ; letzte Taste
   1024 | 22 08 |  | BHI | R | ; >$81?, dann fertig
   1026 | 27 02 |  | BEQ | $2 | ; =$81("-")?, dekrementieren
   1028 | 31 22 |  | LEAY | 2,Y | ; Zeiger inkrementieren (um2, da wieder dekrementiert wird)
   102A | 31 3F |  | LEAY | -1,Y | ; Zeiger dekrementieren
   102C | 20 E3 |  | BRA | W | ; und erneut editieren
   | ; falls Ergebnis nicht "+" oder "-", Ende
   102E | 10 9F 75 | R: | STY | <ADR | ; neue Adresse ablegen
   1031 | 35 33 |  | PULS | A,X,Y,CC | ; Register restaurieren
   1033 | 39 |  | RTS |  | ; zurück zum Monitor

4. Wir gehen nach derselben Methode vor, die bei der ADDRESS-Routine angewandt wurde. Die Anforderungen an die DATA-Routine:

   - Löschen der Anzeige und Ausgabe der Kennung "Da" im Operationsfeld,
   - Ausgabe des zu editierenden Datums und der zugehörigenAdresse,
   - Eingabe des neuen Datums bzw. Inkrementieren/Dekrementieren der Adresse mit +/-,
   - Rückkehr aus der Routine, wenn eine andere Taste gedrückt wurde als eine Ziffer oder "+" bzw. "-".

   Das Flußdiagramm:

   Das Programm:

   Routine DATA
   Eingaberegister:
   Ausgaberegister: B: enthält neue Funktionstaste
   Funktion: Das Datum, auf das der Adressenzeiger des Monitors zeigt, kann editiert werden. Mit den Tasten '+', '-' kann die Adresse inkrementiert/dekrementiert werden.
   1 | CLRDISP | EQU | $F110 | ; Anzeige löschen
   2 | SHOWD | EQU | $F116 | ; D in die Anzeige
   3 | SHOWD7SG | EQU | $F123 | ; D hexadezimal in die Anzeige
   4 | SHOWDATA | EQU | $F150 |
   5 | ADR | EQU | $75 |
   14 | 0000 | 34 73 |  | PSHS | A,X,Y,U,CC | ; Register retten
   15 | 0002 | BD F1 10 |  | JSR | CLRDISP | ; Anzeige Iöschen
   16 | 0005 | CC 5E 77 |  | LDD | #$5E77 | ; "dA"
   17 | 0008 | 8E 00 06 |  | LDX | #6 | ; im Operationsfeld
   18 | 000B | BD F1 16 |  | JSR | SHOWD | ; anzeigen
   19 | 000E | 10 9E 75 |  | LDY | <ADR | ; Adresse aus Systembereich
   20 | 0011 | 1F 20 | LOOP: | TFR | Y,D | ; nach D
   21 | 0013 | 8E 00 02 |  | LDX | #2 | ; im Adreßfeld
   22 | 0016 | BD F1 23 |  | JSR | SHOWD7SG | ; anzeigen
   23 | 0019 | A6 A4 |  | LDA | ,Y | ; zu editierendes Datum
   24 | 001B | 8E 00 00 |  | LDX | #0 | ; im Datenfeld
   25 | 001E | FE F1 51 |  | LDU | SHOWDATA+1 | ; Startadresse + 2
   26 | 0021 | AD 42 |  | JSR | 2,U | ; editieren
   27 | 0023 | A7 A4 |  | STA | ,Y | ; und wieder ablegen
   28 | 0025 | C1 81 |  | CMPB | #$81 | ; letzte Taste "+" oder "-"?
   29 | 0027 | 22 08 |  | BHI | ENDE | ; falls nein
   30 | 0029 | 27 02 |  | BEQ | $2 | ; letzte Taste = "-"
   31 | 002B | 31 22 |  | LEAY | 2,Y | ; "+": Adresse+2 (da wieder
   33 |  |  |  |  |  | ; dekrementiert wird)
   34 | 002D | 31 3F |  | LEAY | -1,Y | ; "-": Adresse dekrementieren
   35 | 002F | 20 E0 |  | BRA | LOOP | ; nächstes Datum editieren
   36 |  | ; |  |  |  |
   37 | 0031 | 10 9F 75 | ENDE: | STY | <ADR | ; neue Adresse ablegen
   38 | 0034 | 35 73 |  | PULS | A,X,Y,U,CC | ; Register restaurieren
   39 | 0036 | 39 |  | RTS |  | ; zurück

   Die Tasten "+" und "-" wirken hier genauso wie bei der ADDRESS-Routine auf die Adresse und nicht auf das zu editierende Datum ein. Das ist sinnvoll, da im allgemeinen aufeinanderfolgende Speicherplätze editiert werden, die so bequem angewählt werden können. Es kommt dagegen selten vor, daß der Inhalt einer Speicherzelle inkrementiert bzw. dekrementiert werden soll.

Zu P3.2-4:

; Routine INSERT
; Die 255 Bytes über der aktuellen Adresse werden um einen Platz nach oben
; der freigewordene Platz wird mit $FF. Dann wird die Adresse inkrementiert und in
; die DATA-Routine gesprungen, so daß das gewünschte Datum eingegeben
; werden kann.
;
EC0E |  |  | ORG | $EC0E |
;
EC0E | 34 17 | INSERT: | PSHS | A,B,X,CC | ; Register retten
EC10 | BD F1 10 |  | JSR | CLRDISP | ; Anzeige löschen
EC13 | 8E 00 06 |  | LDX | #$06 | ; S6 selektieren
EC16 | CC 06 54 |  | LDD | #$0654 | ; "in"
EC19 | BD F1 16 |  | JSR | SHOWD | ; ausgeben
EC1C | 9E 75 |  | LDX | <ADO | ; aktuelle Adresse
EC1E | C6 01 |  | LDB | #1 | ; um 1
EC20 | 3A |  | ABX |  | ; erhoehen
EC21 | 9F 75 |  | STX | <ADO | ; und speichern
EC23 | 50 |  | NEGB |  | ; B = $FF
EC24 | 3A |  | ABX |  | ; X zeigt auf höchste Adresse
EC25 | A6 82 | ILOOP: | LDA | ,-X | ; X dekrementieren, Datum
EC27 | A7 01 |  | STA | 1,X | ; 1 Platz nach oben schieben
EC29 | 9C 75 |  | CMPX | <ADO | ; aktuelle Adresse erreicht?
EC2B | 26 F8 |  | BNE | ILOOP | ; wenn nicht, wiederholen
EC2D | 86 FF |  | LDA | #$FF | ; $FF in
EC2F | A7 84 |  | STA | ,X | ; freigewordene Speicherplatz
EC31 | 35 17 |  | PULS | A,B,X,CC | ; Register restaurieren
EC33 | 13 |  | SYNC |  | ; Ende

Zu P3.2-5:

Da die Routine bereits in Bild 3.2-9 vollständig beschrieben wird, wird hierzu kein Lösungsvorschlag angegeben.

Zu P3.2-6:

Das folgende Listing können Sie erhalten, indem Sie aus dem Praktikumsrechner (mit Hilfe des Programms TERM9.EXE) oder aus dem 6809-Emulator den Speicherbereich $FE00-$FEFF in eine Datei übertragen und diese mit dem Programm DS9.EXE disassemblieren. Studieren Sie es aufmerksam unter Beachtung der Kommentare.

Adresse | OpCode | Mnemocode | Bemerkung
--- | --- | --- | ---
1 |  |  |  |  |  |
2 | 009B |  | ZK | EQU | $9B | ; Zeilenkennung
3 | 009C |  | ZL | EQU | $9C | ; Zeilenlänge
4 | 009D |  | PS | EQU | $9D | ; Prüfsumme
5 | 009E |  | LO | EQU | $9E | ; Lade-Offset
6 | F008 |  | DRACIA | EQU | $F008 | ; Datenregister der ACIA
7 | F009 |  | SRACIA | EQU | $F009 | ; Statusregister der ACIA
8 | F110 |  | CLRDISP | EQU | $F110 |
9 | F116 |  | SHOWD | EQU | $F116 |
10 | F120 |  | SHOWB7SG | EQU | $F120 |
11 | F156 |  | SHOWADR | EQU | $F156 |
12 | E38F |  | MONITOR | EQU | $E38F |
13 |  |  |  |  |  |
14 | FE00 |  |  | ORG | $FE00 |
15 | FE00 | BD FE CE | V24LOAD | JSR | OFFSET | ; 'oF' ausgeben, Lade-Offset einlesen
16 | FE03 | BD F1 10 | JSR | CLRDISP |  | ; Anzeige löschen
17 | FE06 | 7F 00 9B |  | CLR | >ZK | ; Zeilenkennung löschen
18 | FE09 | 7F 00 9D |  | CLR | >PS | ; Prüfsumme löschen
19 | FE0C | BD FE 46 | LOOP_Z | JSR | WAIT_Z | ; auf Zeilenanfang warten
20 | FE0F | 8D 48 |  | BSR | INBYTE | ; Byte empfangen und umwandeln
21 | FE11 | F7 00 9C |  | STB | >ZL | ; als Zeilenlänge abspeichern
22 | FE14 | 8D 43 |  | BSR | INBYTE | ; Byte empfangen und umwandeln
23 | FE16 | 1F 98 |  | TFR | B,A | ; als Zeilenanfangsadresse ZAAH nach Akku A
24 | FE18 | 8D 3F |  | BSR | INBYTE | ; ZAAL empfangen und umwandeln
25 | FE1A | F3 00 9E |  | ADDD | >LO | ; Lade-Offset zu ZAA addieren
26 | FE1D | 1F 01 |  | TFR | D,X | ; Zeilenanfangsadresse nach X
27 | FE1F | 8D 38 |  | BSR | INBYTE | ; Byte empfangen und umwandeln
28 | FE21 | F7 00 9B |  | STB | >ZK | ; als Zeilenkennnung abspeichern
29 | FE24 | 8D 66 |  | BSR | INDATA | ; Daten der Zeile empfangen und
30 |  |  |  |  |  | ; im Puffer mit X abspeichern
31 | FE26 | 8D 31 |  | BSR | INBYTE | ; Byte empfangen und umwandeln
32 | FE28 | 7D 00 9D |  | TST | >PS | ; Prüfsumme testen
33 | FE2B | 26 71 |  | BNE | FEHLER | ; falls ungleich $00, Fehlerausgabe
34 | FE2D | 7D 00 9B |  | TST | >ZK | ; letzte Zeile ?
35 | FE30 | 27 DA |  | BEQ | LOOP_Z | ; nein: Zeilenschleife bearbeiten
36 |  |  |  |  |  |
37 | FE32 | 8E 00 06 | ENDE | LDX | #$0006 | ; Anzeigestelle S6 anwählen
38 | FE35 | CC 79 54 |  | LDD | #$7954 | ; Code für 'En' nach Akku D
39 | FE38 | BD F1 16 |  | JSR | SHOWD | ; darstellen in der Anzeige
40 | FE3B | 30 1E |  | LEAX | -2,X | ; X um 2 dekr., S4 anwählen
41 | FE3D | CC 5E 79 |  | LDD | #$5E79 | ; Code für 'dE' nach Akku D
42 | FE40 | BD F1 16 |  | JSR | SHOWD | ; darstellen in der Anzeige
43 | FE43 | 7E E3 25 |  | JMP | MONITOR | ; Sprung zum Monitor
44 |  |  |  |  |  |
45 | FE46 | BD FE 4E | WAIT_Z | JSR | INCHAR | ; Zeichen über V24 empfangen
46 | FE49 | C1 3A |  | CMPB | #$3A | ; Vergleich mit ':'
47 | FE4B | 26 F9 |  | BNE | WAIT_Z | ; kein Zeilenanfang gefunden
48 | FE4D | 39 |  | RTS |  | ; Rücksprung
49 | FE4E | F6 F0 09 | INCHAR | LDB | SRACIA | ; Lesen des ACIA-Statusregisters
50 | FE51 | C5 08 |  | BITB | #$08 | ; Testen des IRQ-Flags (kann entf.)
51 | FE53 | 27 F9 |  | BEQ | INCHAR | ; Schleife, bis IRQ (dann hier BPL)
52 | FE55 | F6 F0 08 |  | LDB | DRACIA | ; Lesen des ASCII-Zeichens
53 | FE58 | 39 |  | RTS |  | ; Rücksprung
54 | FE59 | 34 12 | INBYTE | PSHS | A,X | ; A,X auf dem Stack retten
55 | FE5B | 8D 1B |  | BSR | WACHAR | ; auf 1. Zeichen warten und umwandeln
56 | FE5D | 58 |  | LSLB |  | ; 1. Hex-Tetrade links verschieben
57 | FE5E | 58 |  | LSLB |  |
58 | FE5F | 58 |  | LSLB |  |
59 | FE60 | 58 |  | LSLB |  |
60 | FE61 | 34 04 |  | PSHS | B | ; 1. Tetrade auf dem Stack sichern
61 | FE63 | 8D 13 |  | BSR | WACHAR | ; auf 2. Zeichen warten und umwandeln
62 | FE65 | EA E0 |  | ORB | ,S+ | ; mit 1. Tetrade verodern und Stack restaurieren
63 | FE67 | 1F 98 |  | TFR | B,A | ; Byte nach Akku A bringen
64 | FE69 | BB 00 9D |  | ADDA | >PS | ; zur Prüfsumme addieren
65 | FE6C | B7 00 9D |  | STA | >PS | ; und abspeichern
66 | FE6F | 8E 00 00 |  | LDX | #$0000 | ; S0 der Anzeige anwählen
67 | FE72 | BD F1 20 |  | JSR | SHOWB7SG | ; Byte anzeigen
68 | FE75 | 35 12 |  | PULS | A,X | ; A,X restaurieren
69 | FE77 | 39 |  | RTS |  | ; Rücksprung
70 | FE78 | BD FE 4E | WACHAR | JSR | INCHAR | ; ASCII-Zeichen einlesen
71 | FE7B | BD FE 7F |  | JSR | ASC2HEX | ; ASCII hexadezimal umwandeln
72 | FE7E | 39 |  | RTS |  | ; Rücksprung
73 | FE7F | C0 30 | ASC2HEX | SUBB | #$30 | ; Offset von $30 abziehen
74 | FE81 | C1 0A |  | CMPB | #$0A | ; Ziffer oder Buchstabe ?
75 | FE83 | 25 02 |  | BLO | ZIFFER | ; Sprung, falls Ziffer
76 | FE85 | C0 07 |  | SUBB | #$07 | ; Buchstaben-Offset ($07) abziehen
77 | FE87 | C1 10 | ZIFFER | CMPB | #$10 | ; Buchstabe aus (A,B,...,F)
78 | FE89 | 24 18 |  | BHS | FEHLER+5 | ; Fehlermeldung
79 | FE8B | 39 |  | RTS |  | ; Rücksprung
80 | FE8C | 34 02 | INDATA | PSHS | A | ; A retten
81 | FE8E | B6 00 9C |  | LDA | >ZL | ; Zeilenlänge laden
82 | FE91 | 27 08 |  | BEQ | RUECK | ; letztes Datum gelesen
83 | FE93 | BD FE 59 | EING | JSR | INBYTE | ; Byte empfangen
84 | FE96 | E7 80 |  | STB | ,X+ | ; im Puffer über X abspeichern
85 | FE98 | 4A |  | DECA |  | ; Datenzähler dekrementieren
86 | FE99 | 26 F8 |  | BNE | EING | ; neues Datum empfangen
87 | FE9B | 35 02 | RUECK | PULS | A | ; A restaurieren
88 | FE9D | 39 |  | RTS |  | ; Rücksprung
89 | FE9E | CC 73 6D | FEHLER | LDD | #$736D | ; 'PS' Fehlermeldung
90 | FEA1 | 20 03 |  | BRA | WEITER |
91 | FEA3 | CC 74 79 |  | LDD | #$7479 | ; 'hE' Fehlermeldung
92 | FEA6 | BD F1 10 | WEITER | JSR | CLRDISP | ; Anzeige löschen
93 | FEA9 | 8E 00 06 |  | LDX | #$0006 | ; S6 in der Anzeige anwählen
94 | FEAC | 34 06 |  | PSHS | A,B | ; A,B retten
95 | FEAE | CC 71 79 |  | LDD | #$7179 | ; 'FE' in S7,S6
96 | FEB1 | BD F1 16 |  | JSR | SHOWD | ; ausgeben
97 | FEB4 | 30 1E |  | LEAX | -2,X | ; X:=X-2, S4 anwählen
98 | FEB6 | CC 74 38 |  | LDD | #$7438 | ; 'hL' in S5,S4
99 | FEB9 | BD F1 16 |  | JSR | SHOWD | ; ausgeben
100 | FEBC | 30 1E |  | LEAX | -2,X | ; X:=X-2, S2 anwählen
101 | FEBE | CC 79 50 |  | LDD | #$7950 | ; 'Er' in S3,S2
102 | FEC1 | BD F1 16 |  | JSR | SHOWD | ; ausgeben
103 | FEC4 | 30 1E |  | LEAX | -2,X | ; X:=X-2, S0 anwählen
104 | FEC6 | 35 06 |  | PULS | A,B | ; A,B restaurieren
105 | FEC8 | BD F1 16 |  | JSR | SHOWD | ; 'PS' oder 'hL' ausgeben
106 | FECB | 7E E3 25 |  | JMP | MONITOR | ; Sprung in den Monitor
107 | FECE | BD F110 | OFFSET | JSR | CLRDISP | ; Anzeige löschen
108 | FED1 | 8E 0000 |  | LDX | #$0000 | ; S0 in der Anzeige anwählen
109 | FED4 | CC 5C 71 |  | LDD | #$5C71 | ; Code 'oF' nach Akku D
110 | FED7 | BD F1 16 |  | JSR | SHOWD | ; ausgeben
111 | FEDA | 30 02 |  | LEAX | 2,X | ; X:=X+2, S2 anwählen
112 | FEDC | BD F1 56 |  | JSR | SHOWADR | ; Offset einlesen
113 | FEDF | 10 BF 00 9E |  | STY | >LO | ; Abspeichern als Lade-Offset
114 | FEE3 | 30 04 |  | LEAX | 4,X | ; S6 anwählen
115 | FEE5 | CC 38 5C |  | LDD | #$385C | ; Code 'Lo' nach D
116 | FEE8 | BD F1 16 |  | JSR | SHOWD | ; ausgeben
117 | FEEB | 39 |  | RTS |  | ; Rücksprung

Machen Sie sich bitte gründlich mit der Funktion ASC2HEX (ab $FE7F) vertraut.

Zu P3.2-7:

Um die Funktionstaste 'F1' mit der der FILL-Routine neu zu belegen, müssen Sie lediglich die Startadresse $1820 in die Speicherzellen $006C,$006D eintragen (s. KE1, Abschnitt 1.2.1).

| 3.2 Das Monitorprogramm |  | Lösungsvorschläge zu den Selbsttestaufgaben |