Jürgen Kehrel
Apple-Assembler lernen Band 2: Nutzung besonderer Apple-Eigenschaften
]ürgen Kehrei· Apple-Assembler lernen
Jürgen Kehrel
Apple-Assembler lernen ,Band 2: Nutzung besonderer Apple-Eigenschaften
Dr. Alfred Hüthig Verlag Heidelberg
Dieje nige n Bezeichnungen vo n im Buch genannte n Erzeugnissen , die zugleich ein getragene Warenze ichen sind , wurd en ni cht besonders ken ntlich gemacht. Es kann also aus de m Fe hlen de r Markierung ® nicht geschlossen we rden , daß die Bezeichnung ein freier Waren name ist. Ebe nsowe nig ist zu entnehme n , ob Patente oder Gebrauchsmu sterschu tz vorli egen.
Als Ergänzung zu diesem Buch ist gesondert lieferbar: »Begleitdiskette zu App le-Asse mbl e r lerne n , Bd . 2« ISBN 3-7785-1244-7
CIP- Kurzt ite laufn ahm e der Deutschen Bibliothek
Kehret, Jürgen: A ppl e-Assemb ler lern en / Jürgen Ke hre!. - Heidelberg: Hüthig Bd . 2. Nutzu ng besonderer A pple-E igenschaften. [Hauptbd.J. -1986 . ISBN 3-7785-1170-X © 1986 Dr. A lfred H üthi g Verlag G mbH Heidelberg Printed in Germany Satz, D ruck und Bindung: La ub GmbH, E lztal-Dallau
5
o. Vorwort " Apple-Assembler lernen" ist ein kompletter Kursus über die Assembler-Programmieru ng des 6502 und 65C02 auf dem Apple II . Im ersten Band lernten Sie sämtliche Maschinenbefehle und wichtige Grundalgorithmen. Der Umga ng mit dem Assembler ASSESSOR wurde geübt. Durch den Simulator IDUS, der sich zusammen mit ASSESSOR auf der Begleitdiskette zum ersten Band befindet, konnten Sie sich Ihre Programme in Zeitlupe ansehen und dabei viel durch Anschaulichkeit lernen. Mit diesen Grundkenntnissen sind Sie jetzt in der Lage , komplexere Aufgaben zu lösen. Der zweite Band stellt Programm e und Unterroutinen vor , um fast all e fundamenta len Probleme auf dem Apple in Maschinensprache zu lösen . Im Gegensatz zu den vielen kurzen Lektionen des ersten Bandes werden wir diesmal weit weniger Schritte ausführen. Die einzelnen Beispiele sind dafür aber auch bedeutend komplizierter , denn fast alle Programme dieses Bandes haben für sich eine sinnvolle Nutzanwendung. Wir werden Musik machen , Fenster und Schrift in hoch auflösender Grafik bearbeiten , Textfiles rasend schnell einlesen , die Möglichkeiten des Applesoft durch einen echten Overlay-Manager erweitern und als Krönung der Bemühungen ein Kopierprogramm schreiben , das auf einem 64K-Apple in 32 Sekunden eine Diskette inclusive Formatierung und Verify kopiert . Wie Sie schon gemerkt haben , ist die Assembler-Programmierung keine Beschäftigung, die man durch reines Zusehen lernt. Sie müssen selbst Programme schreiben, wenn Sie diese Sprache beherrschen wollen. Probieren Sie die Beispiele dieses Buches aus. Verändern Sie sie , experimentieren Sie damit , schreiben Sie ähnliche Programme. Wenn Ihre Fertigkeiten steigen , werden Sie Möglichkeiten finden , das eine oder andere Programm noch zu verbessern. Ideen sind nicht nur Eingabe , sie beruhen auch auf Arbeit und Erfahrung. Mit dem Durcharbeiten des ersten Bandes haben Sie Ihr "Freischwimmer-Zeugn is"
6
Vorwort
in Assembler erworben. Nach dem zweiten Band haben Sie den "Fahrtenschwimmer" errungen. Sie sind jetzt in der Lage , sich allein auf den vielen Pfaden der Apple-Assembler-Programmierung zurechtzufinden und vielleicht noch höhere Auszeichnungen zu ernten. Diese zwei Bände sind mit der tatkräftigen Unterstützung meiner Frau Christiane zustande gekommen , die nicht nur viele Fehler aufgespürt und mich darüberhinaus aufgerichtet hat , sondern die über anderthalb Jahre das meist nachmitternächtliche Arbeitsende mit erleiden mußte. Ihr gilt mein besonderer Dank.
Heidelberg, April 1986
Dr. JÜrgenB. Kehrel
7
Inhalt 5
O. Vorwort . . . . . . . . . . . . . . .
1. Eine Scheibe bleibt nicht matt . . . . . . . . . . . . 1.1 Ordnung im Zei lenchaos . . . . . . . 1.2 Der Niedergang der Zeilen . . . . . . 1.3 Der Vorhang fä llt. . . . . . . . . . . . 1.4 Ausdrucksvermögen . . . . . . . . . . 1.5 80 Zeichen : Schalten und Verwalten 2. Blockmalereien . . . . . . . .
2.1 2.2 2.3
. . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . .
Aus 1 mach 2, das ist das LORES lxI. . . . . . . . . . . .. Switch softly . . . . . . . . . . . . . . . . . . . . . . . . . . . . Mehr als ei n Regenbogen. . . . . . . . . . . . . . . . . . . .
3. Der kleinkarierte Apfel . . . . . . . . . . . . . . . . . . . . . . . . . . . ..
3.1 3.2 3.3 3.4 3.5 3.6 3.7
Hilfe , wo steht der Punkt . . . . . . . . . . . . . . . . . . . Was wären wir ohne ROM! ........ . .... . Eine Linie verschwindet. . . . . . . . . . . . . ..... . Wiederaufführung ... .. . . ....... . .. . ... .. Eine Tabell e mit Bildern . . . . . . . . . . . . . . . . . . . Punkte werden mobil ........ . . . . . . . . ..... Wir "fensterln " ein wenig .. . ..... .... .. . Zeichnen, ohne gesehen zu werden .... . . . . . . . . . Punkt, Punkt , Komma , Strich .... . .. .. ... .... Der Kopfstand der Bytes .... . ... . ... .... . ..
. . . . .
9 9 12 16 19 29 32 32 33 34 41 41 44 46
49 51 54 61
. . .
85
4. DastecktMUSICdrin . . . . . . . . . . . . . . . . . . . . . . . . . . . . ..
100
3.8 3.9 3.10
72
73
8
Inhalt
5. Der mobile Punkt . . . . . . . . . . . . . . . . . . . 5.1 Mit Geschenkpapier und Schleife: packen . . . . . . . . . . . . . . . . . 5.2 Alles ist fließend . . . . . . . . . . . 5.3 Das Zauberpaket wird entschnürt. 5.4 Sich regen bringt Segen. . . . . . .
. . . . . . . . . . . . .. Einpacken und Aus. .... ....... .. . . . . . . . . . . . . .. ....... ...... . .... ... ... ... .
6. Und immer schön variabel bleiben! . . . . . . . . . . . 6.1 Eine Tabelle ist aller Variablen Anfang 6.2 Wer suchet , derfindet . . . . . . . . . . . 6.3 Hin und her , das fä llt nicht schwer. . . . 6.4 Stühle rücken . . . . . . . . . . . . . . . . 6.5 Etwas Ordnung kann nicht schaden. . .
122 122 127 129 138 146
7. Kleinvieh macht auch Mist. . . . . . . . . . . . . . . . . . . . . . . . . . .. 7.1 Konstantim Wandel . . . . . . . . . . . . . . . . . . . . . .. 7.2 Ein Spürhund für Adressen. . . . . . . . . . . . . . . . . . .
155 155 159
8. Speicher-Recycling = Overlay . . . . . . . . . . . . . . . . . . . . . . . ..
168
9. Blitz-Leser 9.1 Ei ne klein e DOS-Enzyklopädie . . . . . . . . . . . . . .. .
191 202
lO.MehrPROalsCONTRA . . . . . . . . . . . . . 10.1 Gute Kontakte per Schnittstell e . 10.2 Wie spreche ich mit ProDOS? . . 10.3 Wo find ' ich ein Zuhause? . . . .
. . .. .. ..
208 208 222 223
11. Schnell wie der Wind . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. 11 .1 Rund und dunkelbraun . . . . . . . . . . . . . . . . . . . .. 11.2 Von halben Bytes und 6&2 . ........ .. . .. . .. . . 11.3 Viele kleine Schalterchen . . . . . . . . . . . . . . . . .. . . 11.4 Das wirbelnde Byte: Byte-Bli zzard . . . .......... .
226 227 230 232 235
Anhänge
269
Stichwortverzeichnis
273
. . . .
. . . .
. . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
106 110 112 118
.. .. .. .. .. ..
. . . .
. . . . . .
106
. . . .
9
1. Eine Scheibe bleibt nicht matt Es gibt nur ganz wenige nützliche Programme , die ohne ein en Dialog mit dem Benutzer auskommen. Dabei steht der Bildschirm als Ausgabemedium an erster Stelle. Ein Programm begrüßt Sie , stellt Ihnen Fragen, macht Ihnen Bedienungsvorsch läge oder teilt Ihnen Fe hl ermeldun ge n mit. Ihre Tastaturein gaben werden normal erweise geechot, damit Sie Ihre Antworten verfo lge n und korrigieren können. Die Qualität ein es Programmes hängt - abgesehen von seinen "inneren" Werten - ganz wesentlich davo n ab , wie erfolgreich es seine Bildschirmausgaben bewälti gt. Wir werden uns deshalb zunächst damit beschäftige n, wie wir gezielt Texte an jede bel iebige Stelle des Bildschirms bringe n können.
1.1 Ordnung im Zeilenchaos Der Apple kann auf seinem Textbildschirm 24 Zeilen (0 - 23) mit je 40 Zeichen (0 - 39) darstellen , also insgesamt 960 Zeichen. Es existi eren zwei Schirmseiten, vo n denen normalerweise nur die Se ite 1 angezeigt und benutzt wird. (Das Wort "Seite" wird hier in einer anderen Bedeutung benutzt als bei dem Wort "Speicherseite" , die 256 Bytes umfaßt.) Im ROM des Apple sind keine Routinen für die Seite 2 vorhanden, so daß ihre Nutzu ng nur durch selbstgeschriebene Assembler-Routinen möglich ist. Da dazu der Aufwand meist größer als der E rfolg ist, führt die Textseite 2 ein Mauerblümchen-Dasein. Jedem Zeichen auf dem Bildschirm entspricht ein Byte im RAM des App le. Die Seite 1 benutzt Speicherstellen von $0400 bis $07 FF, di e Seite 2 von $0800 bis $OBFF. Jedes Zeichen wird durch se inen ASCII (America n Standard Code for Inform ation Interchange )-Wert repräse ntiert. Im Anhang finden Sie eine Tabelle, die Ihnen den Zusamm enhang zwischen ASCII-Code und dargestelltem
10
1. E ine Scheibe bl eibt nicht matt
Zeiche n ze igt. Die Attribu te NORMAL, INVE RS E und FLASH sin d beim Apple abweichend vo n der ASCII-Norm mit in jedes Byte kod iert worde n . Beim Apple IIe und IIc sind fe rne r noch zwei um schaltb are Zeiche nsätze vo rhanden , die bei dem selbe n Code tei lweise andere Bildschirmd arste llungen zur Folge ha be n . A uch hier zeigt Ihne n eine Tabelle im A nh ang die Z usammenhä nge. Die Organisation des Bildschirmspeichers ist beim A ppl e nicht ganz einfac h , auf de n ersten Blick sogar chaotisch. Aufeinanderfolge nde Zeichen innerh alb eine r Zeile stehe n a uch hinterein ande r im RAM. A ufei nande rfo lgende Zeile n stehe n aber leider nicht auch aufeinanderfo lgend im Speicher. Vielme hr wird folgendes Muster verwendet:
Zeile 0 1 2 3 4 5 6 7
Adresse $0400-427 $0480-4A7 $0500-527 $0 580-5A7 $0 600-627 $0 680-6A7 $0700-727 $0780-7A7
Zeile Adresse 8 $0428-44F 9 $04A8-4CF 10 $0528-54F 11 $05A8-5CF 12 $0628-64F 13 $06A8-6CF 14 $0728-74F 15 $07A8-7CF
Seite 1 Seite 2 $LOO $800 $L80 $880 $SOO $900 $580 $980 $600 IAOO $680 $A80 $700 $000 $780 $080 $L28 $828 $LA8 $ 8A8 $528 $928 $5A8 S9A8 $628 $m $6A8 $AA8 $728 ~828 $7A8 $OA8 $850 $LOO S800 $S50 $950 $500 $900 $650 IA50 $600 SAOO 1750 $850 $7 00 $800
sm
Abb. 1: Adress ierung der Textseiten 40Z/Z
Zeile 16 17 18 19 20 21 22 23
Adresse $0450-477 $04DO-4F7 $0550-577 $05DO-5F7 $0650-677 $06DO-6F7 $0750- 777 $07DO-7F7
Scratc h $0478-47F $04F8-4FF $0578-57F $05 F8-5FF $0678-67F $06F8-6FF $0778- 77F $07F8-7FF
1.1 Ordnung im Zei lenchaos
11
Wenn Sie horizontal durch diese Tabelle gehen , so sehen Sie, daß immer 7 Zeilen übersprungen werden. Z u $0400 bis $047F gehören also die Zeilen 0, 8 und 16. Es bleiben 8 Bytes üb rig, die nicht gesehen werden können. Sie sind als sogenannte "Scratchpad"-Stell en (k urzzeitige Zwischenspeicher) den Erweiterungskarten in den Steckleisten (S lots) 1 bis 7 und dem DOS zugeordnet. In ei nigen Asse mbler-Büchern werden Programme vorgestellt, die blitzschnell den Bildschirm löschen, indem der ganze Speicherbereich von $0400 bis $07FF mit Leerzeichen vo llgeschrieben wird. Wundern Sie sich bei solchen "Brutalprogrammen" nicht , wenn hinterher Ihr DOS nicht mehr richtig läuft. Um Text a uf den Bildschirm zu schreiben , müssen Sie die ASCII-Werte der Zeichen in die passenden Speicherstell en schreiben. Im Monitor des Apple existiert eine Routine BASCALC ($FBCl) , die die Anfangsadresse jeder Zei le berechnet, wenn ihr beim Aufruf im Akk umulator die Zei lennummer übergeben wird. Das Ergebnis wird in den Zero-Page-Speicherstellen BASL und BASH ($0028 und $0029) abgelegt. Durch die in direkte indizierte Adressierung mit dem Y-Register können Sie dann auf jedes Byte der Zeile zugreifen: STA (BASL) ,Y mit Y = 0 ... $27.
BASCALC $FBCl Berechnet Basisadresse einer Textzei le (Fenster werden nicht berücksichtigt) E ingabe: Akk u = Bildschirmzeile Ausgabe: BASL ($0028) = Basisadresse Lo BASH ($0029) = Basisadresse Hi
Die Benutzung vo n BASCALC ist recht bequem, für manche Fälle aber zu la ngsam . Dann müssen Sie mit Tabell en arbeiten. Bei unseren HIRES-Programmen we rden Sie ein Beisp iel für diese Techn ik finden.
1. Eine Scheibe bleibt nicht matt
12
1.2 Der Niedergang der Zeilen Scho n von BASIC aus werden Sie das Textfenster kennengelernt haben. D ie Größe des Fensters wird durch die Werte in den Speicherstellen $0020 bis $0023 bestimmt.
$0020 = WNDLFT = lin ker Rand ($00-$27) $0021 = WNDWDTH = Fe nsterbre ite ($00-$28) WNDLFT + WNDWDTH <= $28 (IMMER 11) $0022 = WNDTOP = oberer Ra nd ($00-$18) $0023 = WNDBTM = unterer Rand ($00-$18)
Es gibt keine Routinen, um diese Parameter auf bestimmte Werte zu setzen. Sie müssen die Speicherstellen selber setzen und auf die E inh altung der zulässigen Wertebereiche achte n. Led igli ch zu m Setze n des vollen Textfensters gibt es die Mo ni tor-Routin e SETTXT ($FB39), die zusätzlich von Grafik auf Text umschaltet. D ie vorher aktive Seite bleibt erhalten. A us HGR2 wird so TEXTIl
SEITXT $FB39 Schaltet auf TEXT und voll geöffnetes Fenster Setzt Basisadresse BASLIH auf Zeile $17 (23) Eingabe: A usgabe: WNDLFT = $00, WNDWDTH = $28, WNDTOP = $00 WNDBTM = $18, CV ($0025) = $17, BASLIH = $07DO Dem Applesoft-Befeh l "TEXT" entspricht d ie Routine INIT ($FB2F), die immer auf die Textseite 1 und auf das voll e Fenster stellt.
1.2 Der Niedergang der Zeil en
13
INIT $FB2F Schaltet auf TEXT 1 und voll geöffnetes Fenster Setzt Basisadresse BASLIH auf Zeile $17 (23) Eingabe: Ausga be: WNDLFT = $00 , WNDWDTH = $28, WNDTOP = $00 WNDBTM = $18, CV = $17, BASLIH = $07DO
Um das akti ve Textfenster eine Zeile nach obe n zu rollen (sera il), benu tze n wir SCROLL ($FC70) .
SCROLL $FC70 Ro llt Textfenster eine Zeile nach oben E ingabe: A usgabe: BASLIH = unterste Ze ile, Y
= WNDWDTH
U m das Textfe nster e ine Zeile nach unten zu rollen, müsse n wir eine eigene Ro utin e schreiben. DOWN-SCROLL 1
2 3 4 5 6 7 8 9
10 11
12 13
;************************ ; SeraIl-down für 40Z/Z * ;************************ WNDWDTH WNDTOP WNDBTM BASL BASH BAS2L BAS2H VTAB VTABZ
EQU EQU EQU EQU EQU EQU EQU EQU EQU
$21 $22 $23 $28 $29 $2A $2B $F'C22 $F'C24
1. Eine Scheibe bleibt nicht matt
14
14 15 16 17 18 0300 A5 23 0302 38 19 0303 E9 01 20 0305 48 21 0306: 20 24 FC 22 0309: A5 28 23 030B: 85 2A 24 0300: A5 29 25 030F: 85 2B 26 0311 : A4 21 27 0313 : 88 28 0314: 68 29 0315: 38 30 0316: E9 01 31 0318: 90 11 32 031A: C5 22 33 031C: 90 00 34 03 1E : 48 35 031F: 20 24 FC 36 0322: BI 28 37 0324 : 91 2A 38 0326: 88 39 0327: 10 F9 40 0329: 30 OE 41 42 43 44 032B: AO 00 45 0320: 20 9E FC 46 0330: 4C 22 FC 47
CLEOLZ
EQU $FC9E ORG $300 LDA SEC SBC PHA JSR LOA STA LOA STA LOY DEY PLA SEC SBC BCC CMP BLT PHA JSR LOA STA DEY BPL BMI
LO
LI
WNDBTM
;Untergrenze
11$01
; Zie l zeile ;merken ;Adresse berechnen ;Adresse Lo ; umkopieren ; Adresse Hi ; s.o. als Zie l ;Fensterbreite
VTABZ BASL BAS2L BASH BAS2 H WNOWOTH
;- 1
;Zeilennummer 11$0 1 CLEAR WNOTOP CLEAR VTABZ (BASL),Y (BAS2L) ,Y LI LO
; Que11zeile ;fert ig ;Obergrenze Fenster ; fertig ;Z.nummer merken ;Adresse berechnen ; Que llbyt e ;Zielbyte ; nächstes Byte ; a ll e Byte s fertig? ;Ja , näch ste Zei l e
oberste Ze ile l öschen CLEAR
LOY 11$00 J SR CLEOLZ JMP VTAB
; ganze Zeile ; l ösc hen ; Zeiger-Update
Von unten beginnend wird jeweils die Adresse der letzten (BASL2) und vorletzten Zeile (BASL) berechnet. Die vo rletzte Zeile wird in die letze kopiert . Sind wir am oberen Fensterrand angekommen , wird die oberste Zeile ganz (Y = 0) gelöscht. Unser Programm benutzt noch drei Monitor-Routinen , die wir bisher nicht besprochen haben. VTABZ ($FC24) berechnet die Basisadresseder Zeile im Akkumulator nach BASLlH, wobei das linke Textfenster (WNDLFT) mit eingerechnet wird . VTAB ($FC22) macht dasselbe , nur wird die Zeilennummer aus CV ($0025, ve rtikaler Cursor) genommen. CLEOLZ ($FC9E) löscht die aktuelle Bildschirmzeile (in BASLlH) ab der Position Y nach rechts .
15
1.2 Der Niedergang der Zeilen
VTAB $FC22 Vertikalen Tabul ator setzen unter Berücksichtigung des linken Fensterrandes E inga be : CV = gewünschter VT AB -Wert ($00-$17) A usgabe: BASLIH = Basisadresse der Zeile
VTABZ $FC24 Vertikalen Tab ul ator setzen unter Berücksichtigung des lin ken Fensterrandes E ingabe: Akku = gew ünschter VTAB-Wert ($00-$17) Ausgabe: BASLIH = Basisadresse der Zeile
CLEOLZ $FC9E Löscht bis zum E nde der aktuellen Bi ldschirmzeile . Eingabe: Y-Reg = horiz. Startwert Ausgabe: Y-Reg = WNDWDTH, Akku
= $AO
16
1. Ein e Scheibe bleibt nicht matt
Der Vo llständigkeit halber seien an dieser Stelle bereits sehr wichti ge MonitorRoutinen genannt:
HOME $FC58
Löscht das aktuelle Textfenster und setzt den Cursor in die Ecke oben lin ks. Eingabe: Ausgabe: CH = $00, CV = WNDTOP , Akku = BASL , Y-Reg = $00
CLREOP $FC42
Löscht das aktuelle Textfenster von der Curso rposition bis zu m unteren Ende. Die Curso rpositi on bleibt erhalten. Einga be: Ausgabe: Akku = BASL
1.3 Der Vorhang fällt Da der HOME-Befehl das Textfenster beachtet, lassen sich mit sein er Hilfe einige effektvo lle Löschro utinen schreiben. Da mi t der Vo rh ang langsam fä llt , müssen wir noch eine Verzögerungsschleife einbauen. Der Monitor besitzt dazu die WAIT- Routine ($FCA8) , die über den Akkumulatorinhalt gesteuert wird.
WAIT $FCA8
Zeitverzögerung 13 + 2~ * A + Yl * A2 usec Eingabe: Akku = Verzögerungswert Ausgabe: Akku = $00
1.3 Der Vorhang fällt
17
TEXTLOESCHI
030 0 : 0302: 030 4: 0306: 0309: 030C: 0300: 030F: 03 11 :
A2 86 A9 20 20 E8 EO 90 60
01 21 CO A8 FC 58 FC 29 Fl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
;******************************* Textbildsc hirm löschen * ;******************************* l a ngsam von link s nach rec ht s ORG $30 0 WA lT HOME WNOWOTH LOOP
EQU $FCA8 EQU $FC58 EQU $21 LOX STX LOA JSR JSR l NX CPX BLT RTS
#$0 1 WNOWOTH #$CO WAlT HOME #$29 LO OP
; links be ginn en ;Textfe nster ; Pause ; lös che n ;nächste Spalte ;zu Ende? ;Nein , weiter ;das war ' s
TEXTLOESCH2
0300: 0302: 0304: 0306 : 0309: 030C: 0300 : 030F :
A2 86 A9 20 20 CA 10 60
17 22 CO A8 FC 58 FC F3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
;******************************* lösch en Textbildsc hirm * ;******************************* l angsam von unten nach oben ORG $300 WAlT HOME WNOTOP LOOP
EQU $FCA8 EQU $FC58 EQU $22 LOX STX LOA JSR JSR OEX BPL RTS
#$ 17 WNOTOP #$CO WAlT HOME LO OP
;unten be ginnen ; Pau se l öschen nächste Zeile oben a ngekommen? Ja , fertig
1. Ein e Scheibe bleibt nicht matt
18
TEXTLOESCH3
0300: 0302: 0304: 0306: 0309: 030C: 030D : 030 F': 0311 :
A2 86 A9 20 20 E8 EO 90 60
00 23 CO A8 F'C 58 F'C 19 F' 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
;******************************* löschen Textbildschirm * ;******************************* l angsam von oben nach unten ORG $300 WAIT HOME WNDBTM LOOP
EQU $F'CA8 EQU $F'C58 EQU $23 LDX STX LDA JSR JSR I NX CPX BLT RTS
uOO WNDBTM UCO WAIT HOME U19 LOOP
;oben beginnen ;Pause ;löschen ;nächste Zeile ; fertig? ;Nein, weiter ;zurück
TEXTLOESCH4 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0300 A2 27 15 0302 86 20 16 0304 38 17 0305 : A9 28 18 0307: E5 20 19 0309: 85 21 20 030B: A9 CO 21 030D: 20 A8 F'C 22 0310: 20 58 F'C 23 0313: CA 24 0314: 10 EC 25 0316: 60 26
;******************************* Textbildschirm löschen * ;******************************* langsam von rechts nach links ORG $300 WAIT HOME WNDWDTH WNDLF'T LOOP
EQU EQU EQU EQU
$F'CA8 $F'C58 $21 $20
LDX STX SEC LDA SBC STA LDA JSR JSR DEX BPL RTS
#$27 WNDLF'T
;rechts beginnen
#$28 WNDLF'T WNDWDTH #$CO WAI T HOME
;F'ensterbreite ; anpassen
LOOP
;Pause löschen nächste Spalte fertig? Ja zurück
1.4 Ausdrucksvermögen
19
D as kleine BASIC-Programm TL.DEMO demonstriert Ihn en di e Wirkung aller vier Routinen. Die Maschinenprogramme müsse n dazu unter dem Namen "TEXTLOESCH1.0BJ" bis "TEXTLOESCH4.0BJ" auf der Diskette vo rliegen.
TL.DEMO 5 6 7 8 10 15 20 25 30
REM TEXTBILDSCHIRM-LOESCHER A = 1: TEXT : HOME A$ = STR$ (A) PRINT: PRINT CHR $ (4) "BLOAD TEXTLOESCH"A$".OBJ" FOR I = 1 TO 919 : PRINT "*";: NEXT GET A$ CALL 768 IF A ( 4 THEN A = A + 1: GOTO 7 END
1.4 Ausdrucksvermögen Wie wir einen Text aus e inem Assembler-Programm auf de n Bildschirm ausgeben könn en, haben wir in Lektion 20 des ersten Bandes bereits gesehen. Wir benutzten dazu die Monitor-Routine COUT ($FD ED) , di e das Zeichen im Akku an der ak tuellen Curso rpositi on unter Beachtung der Fenstergrenzen setzt.
COUT$FDED Gibt das Z eichen im Akku auf das aktuelle A usgabegerät (CSW-Vektor siehe Seite 86) aus. Beim Bildschirm werden die Fenstergrenzen beachtet. Die drei R egister Akku , X-Reg und Y-Reg werden zwischengespeichert und so gerettet. Eingabe: CSWLlH Zeiger auf Ausgabegerät (40Z/Z-Bildschirm = $FDFO) Akku = auszugebendes Zeichen Ausgabe: Cursor-Position wird weitergesetzt
20
1. Eine Scheibe bleibt nicht matt
PRiNTl
0300: 0302: 0305: 0307: 030A : 030B : 030D:
AO B9 1"0 20 C8 DO 4C
00 10 03 06 ED FD 1"5 DO 03
0310: C2 E5 E9 031C: 00
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
;***************** Print Nummer 1 * ;***************** ORG $300 DOSWRM COUT
EQU $03DO EQU $FDED
PRINTI PRI
LDY LDA BEQ J SR INY BNE JMP
ENDE TEXT
'ifOO TEXT , Y ENDE COUT
; Laufzähler ;Stringbyte ;ausgeben ;näc hstes Zeichen ;fas t immer
PRI DOSWRM
ASC IIBei sp i el s atz HEX 00
ll
Dieses Verfahren ist angebracht, wenn in einem Programm nur wenige Texte ausgegeben werden müssen. Wollen Sie dieses Programm in ein größeres einbauen , so ersetzen Sie das "JMP DOSWRM' durch "RTS " . Kommen viele Texte vor, dann ist es eine Platzverschwendung , wenn für jede Ausgabe eine eigene Druckroutine geschrieben werden muß . Hier ist ein Unterprogramm notwend ig, mit dem alle Texte ausgegebe n werden können , wenn ihm deren Startadresse und Länge mitgeteilt wird. Das klassische Beispiel ist die PRINT-Routine von Andy Hertzfeld : PRINTI
0300 0303 030C 030D :
20 10 03 D4 E5 F8 00 4C DO 03
0310 0311 0313
68 85 06 68
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
;****************** Print Numm er 2 * ;****************** nac h Andy He rtzfeld ORG $300 PTR DOSWRM COUT
EQU $0006 EQU $03DO EQU $1"DED
DEMO
JSR ASC HEX JMP
PRINT2
PRINT2 IITextprobe 00 DOSWRM
PLA STA PTR PLA
ll
hole Returnadresse vom Stac k
1.4 Ausdrucksvermögen 03 14: 0316 : 0318: 031A: 031C: 03 1F: 0320:
85 AO BI FO 20 C8 00
0322: 0323: 0324 : 0326 : 0328 : 032A: 032C : 0320 : 032 F: 0330:
18 98 65 85 A5 69 48 A5 48 60
07 01 06 06 ED FD F6
06 06 07 00 06
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
21
PR2
ENDE
STA LD Y LDA BEQ JSR I NY BNE CLC TYA ADC STA LDA ADC PHA LDA PHA RTS
PTR+ l UO l ( PTR ). Y ENDE COUT
;String
PR2
;fast immer
+l
; ausgebe n
;Stringl änge ;addieren und PTR PTR PTR+ l UO O
; (merke n ) ;au f den Stack
PTR ; zurückbr in gen ;anspringen
E in Aufruf hat imme r die Form JSR PRINT2 ASC 11 HEX 00
;Ihr Text
Die Druckroutine PRINTI kan n an be li ebige r Stelle stehe n. Ihrem Aufruf durch ,,JSR" fo lgt der Text , der nach dem Pseudo-Opcode " ASe" eingegeben wird. Für inve rse n ode r blinke nde n Text können Sie auch " INV" bzw. "FLS" verwenden. Das Textende ist mit ,,$ 00" gekenn zeichne t. D azu müssen Sie " HEX 00" eingebe n. E in "BRK" führt abe r a uch zum selbe n Ergebn is . W ie arbeitet nun di eses Programm? Bei dem Befehl "JSR PRINTI" wird di e Rücksprungadresse - 1 auf den Stack gescho ben. In un se re m Beispie l ist das $0302 . Di ese A dresse wird durch di e zwei " PLA" -Befehle wieder vom Stack zurückgeho lt und a uf de r Nu ll-Seite (Zero-Page) in "PTR " und " PTR+l" zwische ngespe iche rt. (PTR) ze igt dan n nach $0302. Unser Text beginnt durch die Art des A ufrufs immer an de r folg e nden Adresse, hier be i $0303 . A uf diese Weise "weiß" die Druckroutine , wo de r Text steht. Indire kt indi ziert könn en Sie ihn nun lesen. Wegen des um 1 ve rsetzte n Beginns müssen Sie mit dem W ert 1 im Y -Register anfa nge n. Die sich anschließende Schleife arbe itet im Prinzip wie in PRINTl. Wieder zä hlt das Y-Register die Zahl der ausgegebenen Zeich e n mit. Aus di ese m G rund e kann der Text m ax ima l 254 Zeich e n lang sein. Die ,,00" dient a ls Abbruchkriterium . Die Sch le ife wird übe r " BEQ ENDE" ve rl assen. Die Druckroutine ist damit noch nicht ga nz zu Ende . Durch di e zwe i "PLA" befindet sich keine gü ltige Rücksprungadresse me hr auf dem Stack. D e r Rücksprung darf nicht direkt hinte r de n A ufruf ..JSR PRINT2" e rfo lge n , da hi er ja
1. E in e Scheibe bl eibt nicht matt
22
Text steht und kein ausführbarer Maschinencode. Wir müssen also hinter das "HEX 00" springen. Dazu muß die Adresse von "HEX 00" auf den Stack gebracht werden, denn sie entspricht der Rücksprungadresse - 1. Woher bekommt das Programm diese Adresse? In "PTR" und "PTR + 1" steht noch die alte Rücksprungadresse - 1. Das Y-Register hat di e Zahl der Zeich en vom Textbeginn bis zum "H EX 00" mitgezählt . Wenn wir das Y-Register zu (PTR) addieren, ergibt sich die Adresse des "HEX 00" . Davon muß zu nächst das Hi- und dann das Lo-Byte auf den Stack gebracht werden, bevor uns das "RTS" an di e richti ge Stell e (Adresse vom Stack +1) ins Hauptprogramm zurückführt. Bei di esem Programm ist es wieder lohnend , sich di e einze lnen Schritte im IDUS anzusehen. Lassen Sie sich in der freien Speicheranzeige di e Adressen $0006 und $0007 anzeigen, und setzen Sie den We rt für "Schn ellgang" auf $F800. Unser bisheriges Druckprogramm hat den Nachteil , daß der Text in der gerade aktiven Zeile ausgegeben wird , ohne daß wir einen Einfluß darauf hätten. Wollen wir selbst den Ort bestimmen, müsse n wir dem Aufruf noch ein paa r Zeilen voranstellen. Zunächst wird der horizontale Tabul ato rwert ($00 - $17) nach CH ($0024) geschri eben. Dann rufe n wir mit dem vertikalen Tabulatorwert im Akkumul ator die Routin e TABV ($FBSB) auf, di e un s CV un d BASLIH richti g setzt, so daß der Text an der gewünschten Pos iti on erscheint.
TABV $FBSB Vertik ale Tabulierung unter Berücksichtigung des lin ken Fensterrandes .
Eingabe: Ak ku = gewünschter VTAB-Wert ($00-$17) Ausgabe: CV = VTAB-Wert BASLIH = Basisadresse der Zeile
1.4 Ausdrucksvermögen
23
PRINT3 1 2 3 4 5 6 7 8 9 10 11
0300: 0302: 0304: 0306: 0309: 030C: 0315: 0319 : 0327: 0328:
A9 85 A9 20 20 04 80 09 00 4C
032B: 032C : 032E: 032F' : 0331 : 0333 : 0335 : 0337: 033A: 033B:
68 85 68 85 AO BI F'O 20 C8 00
0330: 033E: 033F': 034 1 : 0343: 0345: 0347 : 0348: 034A: 034B:
18 98 65 85 A5 69 48 A5 48 60
05 24 05 5B 2B E5 80 OE
F'B 03 F'8 AO 20
00 03 06 07 01 06 06 ED F'D F'6
06 06 07 00 06
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
;****************** PRINT Nummer 3 * ;****************** ORG $300 PTR CH DOSWRM TABV COUT
EQU EQU EQU EQU EQU
$0006 $0024 $0300 $F'B5B $F'DED
DEM02
LDA STA LDA JSR JSR ASC HEX INV HEX JMP
#5 ;Cursor horiz. CH #5 ;Cursor vert. TABV PRINT3 "Textprobe" 8D8DAOAO "IN NEUER ZEILE" 00 DO SWRM
PRINT3
PLA STA PLA STA LDY LDA BEQ JSR INY BNE
PR3
ENDE
CLC TYA ADC STA LDA ADC PHA LDA PHA RTS
PTR
; hole Return;adresse vom ;Stack
PTR+l UOl (PTR) , Y ENDE COUT
;String
PR3
;fast immer
+l
;ausgeben
;Stringlänge ;addieren und PTR PTR PTR+l HOO
;(merke n) ;auf den Stack
PTR
;zurückbringen ;anspr in gen
"PRINT3" zeigt Ihnen , wie Sie innerhalb des Textes noch Anweisu ngen unterbringen können, die Sie ni cht über "ASC" usw . einfüge n. ,,8D" ist der Code für < RETURN> , ,,$AO" steht für ein Leerzeichen. D ie zweite Zeile wird also zwe i Zeilen unter der ersten stehen und um 2 Zeichen ei ngerückt sein. Sie kö nnen all e HEX-Werte von $01 bis $FF auf diese Weise in die Ausgabe ei nfügen.
24
1. E ine Scheibe bleibt nich t matt
,,$87" entspri cht z.B. Ctrl-G , was zu einem "Piep" im La utsprecher fü hrt. Pro bieren Sie es einm al aus. Die bisherigen Ro utinen wa ren durch die indizierte indi re kte Adressierung in der Länge des Ausgabetextes begrenzt. Mit "PRINT4" kön nen wir dagegen beliebig lange Texte ausgeben, da hi er di e Zeiger auf der Null -Seite weitergesetzt werden und Y konsta nt bleibt. Auch für die Cursor-Ste ueru ng enthält dieses Progra mm eine Neuerung. Die erste n beiden Bytes nach dem Aufru f der Druckroutine (,,JSR PRINT4") werden als horizontaler bzw. ve rtikaler Tabul atorwert aufgefaßt. Erst danach fo lgt der eigentliche Text. Wenn Sie viel tabulieren müssen, spart dies gege nüber "PRINT3" noch einm al Speicherpl atz.
PRINT4 1
2 3 4 5 6 7 8 9
10 11
0300: 0303: 0305 : 030D : 030 E:
20 OA C2 00 4C
11 03 05 E5 E9 DO 03
03 11: 68
03 12 : 0314: 03 15 : 0317: 031 9: 031C: 031E : 0321: 0324: 0327: 0329: 032C:
85 68 85 AO 20 85 20 20 20 FO 20 4C
06 07 00 35 24 35 5B 35 06 ED 24
03 03 FB 03 FD 03
032 F : 20 35 03 0332 : 6C 06 00 0335 0337 0339 033B 033D
E6 DO E6 BI 60
06 02 07 06
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
;****************** Print Numme r 4
ORG $300 PTR CH DOSWRM TABV COUT
EQU EQU EQU EQU EQU
$0006 $0024 $03DO $FB5B $FDED
DEM03
JSR HEX ASC HEX JMP
PR I NT4 OA05 ; Cur. harz. , vert. "Beispiel " 00 DOSWRM
PRINT4
PLA STA PLA STA LDY J SR STA JSR J SR JSR BEQ JSR JMP
PR4
30
31 32 33
34 35 36 37 38 39 40
*
;******************
PTR PTR+l *00
I NKREM CH INKREM TABV I NKREM ENDE COUT PR4
;Returnadresse ;vam Stack ;ziehen und ;merken ; ini t i a li s i ere n ; nächst. Z. ;Cursar harz. ; näc hst. Z. ;Zeiger setzen ; näc hst. Z. ;String ausgebe n ;immer
ENDE
JSR INKREM JMP (PTR)
;hinter Text ;zurückspringen
I NKREM
INC BNE INC LDA RTS
;Zeiger wei;terschieben
LADEN
PTR LADEN PTR+l (PTR), Y
;Z. laden
1.4 Ausdrucksvermögen
25
Schauen Sie sich auch dieses Beispiel im IDUS an, besonders den Rücksprung in Zeile 33/34. Die verschiedenen Möglichkeiten ei ner Druckroutine sind noch längst nicht ausgereizt. "PRINT5 " ze igt eine weitere Variation sowohl in der Cursorsteue rung, die hier über den Akkumulator und das X-Register e rfolgt, als auch für das Weitersetzen des Zeigers (PTR). Die dritte Änderung liegt in der Kennzeichnung des Textendes. Bisher brauchten wir mit ,, $00" ei n Extrabyte. Jetzt benutzen wir das Bit 7, um das letzte Zeichen zu finden. " DCI" inverti ert im letzten Zeich e n der Zeichenkette das Vorzeichen. In diesem Beispiel ist Bit 7 bis auf das letzte Zeichen imme r gese tzt . Das Vorzeichen jedes ASCII-Wertes wird gerettet (Zeile 42) und nach der Ausgabe wieder zurückgeho lt (Zeile 45). War Bit 7 gesetzt , geht der Text noch weiter , war Bit 7 gelöscht - der Wert also positiv - , ist das Ende e rreicht. Da wir bei dieser Technik nicht die Pseudo-Opcodes "INV" und "FLS" verwenden dürfen , benutzen wir eine andere Möglichkeit, zusa mmen mit COUT die Attribute zu bestimmen. Die Monitor-Routine SETINV ($FE80) sorgt für inverse Textausgabe, SETNORM ($FE84) schaltet auf normale Ausgabe. Ein FLASH müssen Sie selber schreibe n durch LDA if$7F
STA INVFLG (= $0032).
SETNORM $FE84 Schaltet a uf normale Bildschirmdarstellung bei Textausgabe über COUT. Eingabe: Ausgabe: INVFLG = $FF, Y-Reg = $FF
SETINV $FE80 Schaltet auf inverse Bildschirmdarstellung bei Textausgabe über COUT. Eingabe: Ausgabe: INVFLG
= $3F , Y-Reg = $3F
26
1. E in e Sch eibe bleibt nicht matt
PRINTS 1 2 3 4 5 6 7 8 9 10 11
0300: 0302: 0304: 0307: 0311 : 0313: 03 15 : 0318 : 0324: 0327: 0329: 032B: 032E: 033B:
A9 A2 20 CE A9 A2 20 CA 20 A9 A2 20 07 4C
05 OA 41 CF 07 OA 3E C5 84 09 OA 41 C9 00
033E: 0341: 0343: 0346: 0347: 0349: 034A: 034C: 034E: 0350 : 0352 : 0354 : 0356 : 0357: 0359 035C 0350 035F 0361 0362 0364 0365
20 86 20 68 85 68 85 AO E6 00 E6 BI 48 09 20 68 30 A5 48 A5 48 60
80 FE 24 5B FB
03 02 03 04 FE 03 C5 03
06 07 00 06 02 07 06 80 ED FD EF 07 06
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
;****************** PRINT Nummer 5 * ;****************** ORG $300 PTR CH DOSWRM TABV COUT SETINV SETNORM
EQU EQU EQU EQU EQU EQU EQU
$0006 $0024 $0300 $FB5B $FDED $FE80 $FE84
DEM04
LDA LDX J SR DCI LDA LDX J SR DCI J SR LDA LDX J SR DCI JMP
;Cursor vert, *5 HO ;Cursor horz , PRINT5 "NORMAL UND "
PRINT5I PRINT5
PR5 PR5A
J SR STX J SR PLA STA PLA STA LDY INC BNE IN C LDA PHA ORA J SR PLA BMI LDA PHA LDA PHA RTS
n
HO PRINT5I "JETZT INVERS" SETNORM *9 HO PRINT5 "WIEDER NORMAL" DOSWRM SETINV CH TABV PTR PTR+l *00 PTR PR5A PTR+l (PTR ), Y U80 COUT PR5 PTR+l PTR
; Inver s maske ;Cursor horz. ;Curso r vert , ;Re turnadres se ;vom Stac k ;und speicher n ; initi a l s ieren ;näc hs t es Z, ;Übertrag? ;JA ; Ze ic hen laden ;Vorzeichen me rke n ; Bit 7 setzen ;ausge ben ; Vorzei chen hol en ;Pos itiv a ls Ende ; Rüc kspru ngadr esse ;auf den ;Stack sc hieben ;anspringe n
27
1.4 Ausdrucksvermögen
Wenn Sie den A pplesoft-Interpreter mitbenutzen wo llen, können Sie eine ganz kurze Druckroutin e schreiben. STROUT ($DB3A) gibt ein en Text mit bis zu 255 Zeichen über COUT aus. Der Text kann all erdings nicht direkt hinter dem A ufruf mit "JSR STROUT" liegen, da STROUT die Rücksprungadresse nicht weitersetzt. Sie benötige n also wie bei PRINTl einen sepa raten Platz für den Text. Die Adresse des ersten Bytes muß im Akkumulator (Lo) und Y-Register (Hi) übergeben werden. A ll e Zeichen müssen mit gelöschtem Bit 7 vo rliegen. Das Texte nde muß durch ,,$00" oder ,,$22" geken nzeichnet sein . Das bedeutet , daß Sie A nführungszeichen oben (") nicht mitdrucken könne n!!
STROUT $DB3A Gibt ein e Z e ichen kette aus, die mit Bit 7 = 0 vo rli egt und mit $00 oder $22 endet. Eingabe: Akku = Lo-Byte vom Zeichenkettenstart Y-Reg = Hi-B yte vo m Ze ichenkettenstart A usga be: Akku = letztes ausgege be nes Zeichen Y-Reg = Anzahl der Z eichen + 1 TXTPTR ze igt auf Z eichen hinter dem Strin g
PRINT6 1 2 3 4 5 6 7 8 9 10 11
0300: 0303: 0306 : 0308: 030A: 030D:
20 20 A9 AO 20 4C
2F 58 10 03 3A DO
FB FC DB 03
12 13 14 15 16 17 18 19 20
;****************** PRINT Nummer 6 * ;****************** benutzt App1esoft ORG $300 DOSWRM STROUT INIT HOME
EQU EQU EQU EQU
$03DO $DB3A $FB2F $FC58
DEM05
J SR J SR LDA LDY JSR JMP
I NIT HOME *
TEXT STROUT DOSWRM
;Textb i1dschi r m ; 1ösc hen ; Lo-By t e ; Hi- Byte ;String ausgeben
28
1. Ein e Scheibe bleibt nicht matt
0310 : 54 65 78 0322: 00
21 22
TEXT
ASC ' Text mit Applesoft' HEX 00 ; Ende-Kennun g
Die Textausgabe über STROUT hat noch eine weitere Eigenschaft , die sie vo n allen anderen Routinen unterscheid et: Sie können die Geschwindigkeit steuern. Je nach Inhalt von SPEED ($00F1) werden zwischen den ei nzelnen Zeiche n Verzögerungssch leifen durchl aufen. Ein Wert von $01 ergibt die maxim ale Geschwindigkeit , die bis $FF immer weiter herabgesetzt wird. Mit $00 erreichen Sie di e größte Verzögerung.
PRINTI 1 2 3 4 5 6 7 8 9 10 11
0300: 0303: 0306: 0308 : 030A : 030C: 030E : 0310: 0313: 0315: 0317: 031A : 031C : 031E:
20 20 A9 85 A9 85 A9 20 A9 AO 20 A9 85 4C
2F' 58 80 F'1 05 24 07 5B 21 03 3A 01 F'l DO
F'B F'C
F'B DB 03
032 1 : 54 65 78 0333: 00
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
;****************** PRINT Nummer 7 * ;****************** benutzt App l esoft ORG $300 CH SPEED DOSWRM STROUT INIT TABV HOME
EQU EQU EQU EQU EQU EQU EQU
$0024 $00F'l $03DO $DB3A $F'B2F' $F'B5B $F'C58
DEM06
J SR J SR LDA STA LDA STA LDA JSR LDA LDY J SR LDA STA JMP
INIT HOME U80 SPEED *5 CH
TEXT
Textb il dschirm lö sc hen verzögern
n
TAB V *< TEXT *> TEXT STROUT *01 SPEED DOSWRM
; Lo-Byte ;Hi-Byte ;Str ing ausgeben ;zurücksetzen
ASC 'Text mit Appl esoft' HEX 00 ; Ende-Kennung
Jede der hier vorgestellten Routin en hat ihre Vor- und Nachtei le. Welche Sie im konkreten Fall anwenden, hängt zum Te il von den Anforde rungen des Programms ab, ist aber auch Ihrer freien Entscheidung (= Geschmack?) unterworfen . Ich persön lich benutze am häufigsten "PRINTI" .
29
1.5 80 Zeichen: Schalten und Verwalten Professionelle Programme verl ange n in der Regel nach einer Textausga be mit 80 Zeichen pro Zeile. Beim alten Apple II + ist dies nur mit einer Z usa tzkarte zu erreichen. Am verbreitetsten ist das VIDEX-System, das einen eigenen Bildschirmspeicher besitzt. Nähere Informationen zum Aufbau des VIDEX-B ildschi rms finden Sie im Peeker Nr. 1/2 vo n 1985 ab Seite 42 . De r Apple IIe benötigt eine andere Zusatzkarte , die im Hc bereits fest eingeba ut ist. Die Hä lfte de r Daten fi ndet sich dabei an den se iben Speicherstell en wie bei der 40-ZeichenDarstell ung: von $0400 bis $07FF. Die andere Hä lfte befindet sich auf den se lben Ad resse n des Zusatzspeichers (AUX-Memory) der E rwe ite rungskarte. Da beide Speicherbereiche den se lben Adressraum belegen , muß zwischen ihnen hin- un d hergeschaltet werden. Dies wird von de r Anzeigeelektro ni k automatisch vo rgenom men. Die Spalten mit un gerader Numm er liege n im Ha uptspeicher (Mai n) , die Spalten mit gerader Num me r im Zusatzspeicher (AUX). AU X MAI N AUX MA IN AUX MAIN AUX MA lM AUX MAIN AUX $00 $00 $01 $01 $0 2 $02 $03 $03 $01. $01. $05
-
$01.00
A P
P
L
$01.80
A S
S
E M B
$0500
L
E
R N
E N
$0580
B
A N D
2
E
L
E
R
Abb. 2: Ad ressierun g der 80Z/Z Textseite
Um Daten direk t auf den 80-Zeichen -Schirm zu speichern oder zu lesen, müsse n Sie zu nächst den Softswitch 80STOREON ($C001) betätigen, in dem Sie irgendein en beli ebige n Wert dorthin speichern (STA $C001) . Wenn 80STORE auf diese Weise angeschaltet wurde , wird mit den Softswitches LOWSCR ($C054) lind HISCR ($C055) nicht mehr zwischen den Textseiten 1 lind 2 hin- lind
1. Eine Scheibe bl eibt nicht matt
30
hergeschaltet , sondern zwischen dem Haupt- und dem Erweiterungsspeicher der 80-Zeichenkarte. ungerade Spalten bearbeiten LDA UOO STA 80STOREO N ($C001) STA LOWSCR ($C054)
gerade Spal ten bearbeiten LDA UOO STA 80STOREON($C001) STA HI SCR ($C055)
80STORE wird wieder abgeschaltet durch das Schreiben nach 80STOREOFF ($COOO). Achtung: Di ese Adresse ist identisch mit der Tastaturad resse. Wenn Sie aus di eser Adresse lesen (z.B. LDA , BIT) , erhalten Sie die Tastat urinform ation. Wenn Sie in diese Adresse schreiben (z.B. STA) , schalten Sie 80STORE ab. Wenn Sie nur einfac h Texte über COUT auf den 80-Zeichen-Schi rm ausgeben wollen , brauchen Sie sich um die Softswitches ni cht zu kümmern . Sie müssen led iglich das Zusatz-ROM im Adressbereich von $C300-$C3FF einschalten durch ein "JSR $C300". COUT funkti oni ert dann automatisch auch mit der 80-Zeichenkarte, und Sie können unsere Druckroutinen PRINTI bis PRINTI benutze n. Ein Schönhei tsfehler ist allerd in gs dabei: der horizo ntale Tabulator funktioniert nicht richtig, da die 80-Zeichenkarte den horizonta len Cursorwert nicht bei $0025 so ndern bei $057B in einem der Scratchpad-Bytes verwa ltet. Erfreulicherweise tut auch die VIDEX-Karte dies, so daß das folgende Programm sowohl mit der VIDEX-Karte als auch mit de r Apple-Karte läuft .
PRINT DEMO 80Z/Z 1 2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19
;******************** PRINT DEMO 80Z/Z * ;******************** App1e IIe/e oder VIDEX 80 Zeiehenkarte in Slot 3 ORG $300 PTR HORZ DOSWRM CH BASIC I NT TAB V COUT SETINV SETNORM
EQU EQU EQU EQU EQU EQU EQU EQU EQU
$0006 $0008 $03DO $057B $C300 $FB5B $FDED $FE80 $FE84
31
1.5 80 Zeichen: Schalten un d Verwalten 0300: 0302: 0304 : 0307: 030A: 030B: 030D: 030F': 03 11 : 0313: 0315:
A9 85 20 20 18 A5 69 85 C9 90 4C
00 08 00 C3 18 03
20 21 22 23 24 08 25 OD 26 08 27 42 28 F'2 29 DO 03 30 31 0318 : A9 05 32 03 1A: A6 08 33 031C: 20 57 03 34 031F': CE CF' D2 35 36 0329: A9 07 032B: A6 08 37 032D: 20 54 03 38 0330: CA C5 D4 39 033C: 20 84 F'E 40 41 033F': A9 09 0341: A6 08 42 0343: 20 57 03 43 0346 : D7 C9 C5 44 45 0353: 60 46 0354: 20 80 F'E 47 0357: 8E 7B 05 48 035A: 20 5B F'B 49 035D: 68 50 51 035E: 85 06 0360: 68 52 0361: 85 07 53 54 0363: AO 00 0365: E6 06 55 0367: DO 02 56 0369: E6 07 57 036B: BI 06 58 036D : 48 59 60 036E: 09 80 0370: 20 ED F'D 61 0373: 68 62 0374: 30 EF' 63 64 0376: A5 07 0378: 48 65 0379: A5 06 66 037B: 48 67 037C: 60 68
DEM07 DM
DM2
PRINT8I PRINT8
PR8 PR8A
; ini tialisieren
LDA STA J SR JSR CLC LDA ADC STA CMP BLT JMP
*00 HORZ BASICINT DM2
LDA LDX JSR DCI LDA LDX JSR DCI JSR LDA LDX JSR DCI RTS
;Cursor vert. *5 ;Cursor horz. HORZ PRINT8 "NORMAL UND "
;80Z/Z ei n
HORZ *13 HORZ *66 DM DOSWRM
1f7
HORZ PRINT8I "JETZT INVERS" SETNORM *9 HORZ PRINT8 IOWIEDER NORMAL "
JSR SETINV STX CH JSR TABV PLA STA PTR PLA STA PTR+l LDY *00 INC PTR BNE PR8A I NC PTR+l LDA (PTR), Y PHA ORA U80 JSR COUT PLA BMI PR8 LDA PTR+l PHA LDA PTR PHA RTS
; Inversmaske ; Cursor horz. ;Cursor vert. ;Returnadresse ;vom Stack ;und speichern ;initia1 s ieren ;nächstes Z. ;Übertrag? ;JA ;Zeichen laden ;V orze ichen merken ;Bit 7 setze n ;ausgeben ;Vorzeichen holen ;Positiv a ls Ende ; Rü cksprungadresse ;auf den ;Stack schieben ;anspr in gen
32
2. Blockmalereien Neben der Textdarstellung besitzt de r Apple di e Fä higke it, Grafiken in nied riger und hoher Auflösung anzuzeigen. Die niedrigauflöse nde Grafi k (LORES) erfre ut sich nu r mäßiger Beliebtheit, obwo hl sie immerhin über 16 Farben verfü gt und einfach zu programmieren ist. Wenn Sie fa rbige Rechtecke darstellen müssen, gibt es zu LORES keine Alternative . Der Nachteil von LORES ist se in e grobe bl ockartige Struktur , da di e Anzeige aus 1920 kleinen Rechtecken besteht , die in 48 Reihen zu je 40 Spalten angeordn et sind .
2.1 Aus 1 mach 2, das ist das LO RES Ix1 Die LO RES-Grafik belegt den se lbe n Speicherpl atz wie die Textse iten. Es gibt ebenfa lls zwei anzeigbare LO RES-Se iten: LORESI beginnt bei $0400 und endet mit $07FF, wä hrend LORES2 den Speicher vo n $0800 bis $OBFF beansprucht. Zu jedem Byte gehören 2 überein ander liegende Rechtecke, deren Farbe un abhängig voneinander wählbar ist. Die Orga ni sati on des LORES-Bildschirms entspricht dem der Textseite, wenn Sie sich vorstellen, daß jede Textzeile horizo ntal in zwei Grafikzeilen gespalten ist. Zu Textzeile 0 gehören die Grafikzeilen 0 und 1, zu Textzeile 1 gehören die Grafikzeil en 2 und 3 usw. Jedes Speicherbyte besteht aus 2 Nibb les. In der hexadezima len Schreibweise sind sie mit den beiden Ziffe rn der HEX-Zahl identisch. $F6 besteht aus dem Nibble $F und dem Nibbl e $6 . Das linke Nibble bestimmt di e Farbe der unge radzahligen Grafikzeilen (= unten), das rechte Nibble ist für di e geradzahligen Zeil en (= oben) da. E in Nibbl e kann die 16 Werte von $0 bis $F ann ehm en. Ihn en entsprechen die 16 darstellbaren Fa rben.
2.2 Switch softly
33
LORES Farbtabelle
Wert Farbe
Wert Farbe
$0 $1 $2 $3 $4 $5 $6 $7
$8 $9 $A $B $C $D $E $F
Schwarz Fuchsinrot Dunkelblau Purpur Dunkelgrün Grau 1 Blau Hellblau
Braun Orange Grau 2 Rosa He llgrün Gelb Aquamari n Weiß
Die Farbbezeichnungen sind so von der Firma Apple angegeben worden. Die tatsächlichen Farben auf Ihrem Monitor kö nnen davon abwe ichen. Das Byte $6D wü rde demnach ein gelbes Rechteck über einem blauen ze igen.
$6 0
$00
$01/ $02 $ 03 o I 10 10 10 $OLOO hi 6 hi hi 10 10 10 10 _ .. _ .. $OLBO _hi.... -- hi .. ....hi _- - -_hi.... 10 .. -_ 10 .... .. .... 10 .. - ....10_.... $05 00 - -h--i hi hi hi
SOL $05 $06 $07 $OB . -10- .. --10 - .. - -10--- - -10---- 10 ~
~
hi hi 10 10 .. ........ hi hi 10 -_10.. .. hi hi ..
..
•
0 .
hi 10 hi 10 hi
S09 $OA 10 10 hi hi hi hi 10 _JQ ._ 10 _.19 ___ hi hi hi hi 10 10 10 _JQ_ hi hi hi hi
Abb . 3: Ad ressierung der LORES-Seite 1
2.2 Switch softly Bereits beim Textbildsch irm haben wir kennengelernt , daß die Anze ige des Apple durch ein ige Speicherstellen gesteuert wird , die "Softswitches" genannt werden. Wenn wir die 80-Zeichen-Karte des He und Hc einmal außer acht lassen , gibt es fo lgende Möglichkeiten:
34
2. Blockmalereien
Schalter
Fun kti on
$C050 TXTCLR $C051 TXTSET
Schaltet Grafik ein Schaltet Text ein
$C052 MIXCLR $C053 MIXSET
Nur Text oder Grafik Grafik mit 4 Zeilen Text
*
$C054 LOWSCR Seite 1 von Grafik oder Text Se ite 2 von Grafik oder Text $C055 HISCR $C056 LORES $C057 HIRES
ni edriga uflöse nde G rafik hochauflösende Grafik
*
*
* D iese Zustände sind nur sichtbar , wenn TXTCLR betätigt wird. Sie können die Schalter stellen, indem Sie entweder aus der Speicherstelle lesen oder in di ese schreiben. Durch die Befeh lsfo lge
LDA TXTCLR LDA MIXCLR LDA LOWSCR LDA LORES wird die Anzeige des gesamten LORES-Grafikschirms der Seite 1 ausgewählt. Es kommt dabei nicht auf die Reih enfolge an, in der die Schalter betätigt werden!
2.3 Mehr als ein Regenbogen Die von Applesoft benutzten Routinen für das Zeichen vo n LORES-Grafik sind Bestandteil des Monitors . Wir können sie von einem Assemb ler-Programm aus sehr einfach mitbenutzen. Sie funktionieren allerdings nur für die LORES-Seite l. Das fo lgende Demonstrationsprogramm setzt zunächst den LORES-Grafikschirm mit 4 Textzeilen am unteren Rand durch den Aufruf von SETGR ($FB40). Dies funktioniert allerdings nur , wenn vorher der Textbildschirm
2.3 Mehr als ein Regenbogen
35
angeschaltet war. Wo llen Sie auch von HGR nach LORES umschalten , müssen Sie di e Applesoft-Routine GR ($F390) benutzen.
SETGR $Fß40 Schaltet um auf Grafik und gem ischte Darstellung. Das Textfenster wird geöffn et, der obere Teil gelöscht, wenn es sich um LORES handelt. E ingabe: A usgabe: Y-Reg = $FF , BASLIH zeigt auf Zeile $17 COLOR = $00 gesetzt
GR $F390 Schaltet auf LORES-Grafik und gem ischte Darstellung. Textfenste r geöffnet, Curso r in der letzten Zeile, LORES-Farbe Schwarz ak tiv. E ingabe: A usga be: Y-Reg = $FF, BASLIH zeigt auf Zei le $17 COLOR = $00
Als nächstes werden 16 horizontale Linien in allen Farben gezeichneL Zum Setzen einer Farbe wird deren N umm er in den Akk umul ator geladen und dann SETCOL ($F864) aufgerufen. Hori zonta le Linien werden entsprechend dem BASIC-Befehl HLIN XL ,XR AT Y durch HLINE ($F819) gezogen, wobei die Koo rdin ate n im Y-Register (XL), der Zero-Page-Adresse H2 ($002C) (XR) und im Akk umul ator (Y) überge ben werden.
2. Blockmalereien
36
SETCOL $F864 Setzt die LORES-Farbe Eingabe: Akku = Farbnummer ($0 ... $F) Ausgabe: COLOR ($0030) gesetzt
HLINE $F819 Zeichnet horizontale Linie von XLinks nach XRechts in der Zeile Y. Eingabe: COLOR gesetzt , Y-Reg
= XL , H2 ($003C) = XR , Akku = Y
Ausgabe: -
Um den Bildschirm mit vertikalen Linien zu füllen, benutzt das Demo-Programm die Routine VLINE ($F828). Dies geschieht in einer Schleife, der das Y-Register als Laufvariable dient. Da die Farbwerte nur zwischen $00 und $OF liegen dürfen, wird mit einem "AND $OF" das obere Nibble ausgeblendet.
VLINE $F828 Zeichnet vertikale Linie von YOben bis YUnten in der Spa lte X. Eingabe: COLOR gesetzt , Akk u
= YO , V2 ($002D) = YU,
Y-Reg
=X
Ausgabe: -
Darunter kann dann der Benutzer eine Doppellinie eingeben , indem jeder Tastendruck als ASCII-Zeichen direkt in den LORES-Speicher geschrieben und damit sichtbar wird. Die Routine CLRTOP ($F836) löscht die oberen 40 LORES-Zeilen , läßt aber den Text intakt. Mit CLRSCR ($F832) können Sie den ganzen LORES-Schirm löschen , wenn Sie den Softswitch $C052 vorher betätigen. Bei der gem ischten Darstell ung fü llt sich das Textfenster mit in verse n @.
2.3 Mehr als ein R egenbogen
37
CLRTOP $F836 Löscht die oberen 40 Zei len de r LORES-Grafik 1. E ingabe : Ausgabe: Y-Reg = $FF, Akku = $27 , COLOR = $00
CLRSCR $F832 Löscht a lle 48 Zeilen der LORES-Grafik 1. E in gabe: A usgabe: Y-Reg = $FF, Akku = $2F, CO LOR = $00
CLRSC2 $F838 Löscht Y Z e il en der LORES-Grafik 1. E ingabe : Y-Reg = Zah l der zu lösche nde n Zei le n (von oben). A usgabe: Y-Reg = $ FF, Akku = Zei le nza hl , COLOR = $00
D en Absch luß des Demoprogramms bildet eine kleine B lockgrafik, di e Punkt für Punkt gesetzt wird. Die Koordinaten li egen in ein e r Tabelle und werden mit PLOT ($F800) um gesetzt.
PLOT $F800 Zeich net einen Punkt X ,Y in der Farbe COLO R. E ingabe: COLOR gesetzt , Akku Ausgabe: -
= Y , Y-Reg = X
2. Blockmalereien
38
LORES 1 2 3 4 5 6 7 8 9 10 11
0803: 20 40 F'B
0806: 0808: 0809: 080C: 080 E: 08 10: 0812: 0813: 08 16: 08 17 :
0819 08 1B 081C 08 1E 0821 0823 0825 0827 082A 082B
A2 8A 20 AO A9 85 8A 20 CA 10
AO 98 29 20 A9 85 A9 20 88 10
OF' 64 F8 00 27 2C 19 F8 EF
27 OF 64 F8 25 2D 10 28 F8 EE
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
;******************************* Lo-Res Beisp i elprogramm * ( C) 1986 Dr. Jürgen Kehrel * ;******************************* H2 V2
EQU $002C EQU $002D
KBD STROBE
EQU $COOO EQU $COIO
PLOT HLINE VLINE CLRSCR CLRTOP SETCOL SETGR
EQU EQU EQU EQU EQU EQU EQU
$F'800 $F'8 19 $F'828 $F'832 $F'836 $F'864 $F'B40
ORG $0803 START
J SR SETGR
;Grafik ein
16 horz. Lini en in a ll en Farben LOOP
LDX TXA JSR LDY LDA STA TXA JSR DEX BPL
UOF
;Beginn "Weiß"
SETCO L 41'$00 41'$27 H2
;Farbe ; X-Links ;X-Rechts ;Y-Wert
HLINE LOOP
Den Bildschirm mit vert. · Linien füllen LOOPI
LDY TYA AND JSR LDA STA LDA JSR DEY BPL
41'$27
;X-Wert
UOF SETCO L 41'$25
;ausblenden ;Y-Unten
V2
41'$10 VLINE
;Y-Oben
LOOPI
Eine "Zei l e " vom Benutzer eingeben l assen
2.3 Me hr als ein Rege nbogen
082D : 082F: 0832: 0834 : 0837: 083A: 083B: 083D:
083F: 0842: 0844: 0847: 0849: 084C: 084E: 084F: 0850: 085 3 : 0856 : 0857:
A2 AD 10 8D 9D E8 EO 90
20 A9 20 A2 BD FO A8 E8 BD 20 E8 DO
00 00 CO FB 10 CO DO 05 28 FO
36 F8 OF 64 F8 00 5A 08 OB
02 02 04 07 07 OA 09 OC OC OE OD 14 11 11 12 19 16 19 lC 16 16 18 17 17 IB IB
LOOP2
5A 08 00 F8 FO
06 OA OC 07 OB OA 06 06 OA 06 09 06 07 OB OC 06 08 OB 09 11 15 17 14 11 11 15
02 02 05 07 08 OA 08 OC OC OF OD 13 11 11 13 18 17 18 ID 16 16 19 19 IB IB
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
LDX LDA BPL STA STA 1NX CPX BLT
#$00 KBD LOOP2 STROBE $05DO,X #$28 LOOP2
Schirm löschen, Bild aufbauen
LOOP3
72
0859: 60
085A: 0862 : 086A: 086 E: 0876: 087E: 0886: 088A: 0892: 089A: 08A2: 08AA: 08B2: 08BA: 08C2: 08C8: 08DO: 08D8: 08EO: 08E6 08EE 08F6 08FE 0906 0908 0910
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
39
ENDE
JSR LDA JSR LDX LDA BEQ TAY 1NX LDA JSR 1NX BNE
;Weiß ; init. ;X-Wert
TAB , X PLOT
;Y-Wert
LOOP3
RTS
; Tabelle X, Y. TAB
CLRTOP #$OF SETCOL #$00 TAB , X ENDE
HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX
(max. 254 Werte) 0206020702080209 020A020B020C030C 040C050C ;L 070707080709070A 070B080C090COAOB OAOAOA090A080A07 09060806 ;0 OC060C070C080C09 OCOAOCOBOCOCOD06 OE060F070F080E09 OD090DOAOEOBOFOC ;R 1406130612061106 110711081109110A 110BII0C12091309 120C130C140C :E 1906180617061607 160817091809190A 190B180C170C160C ;S lC091D091E09 ;1611161216131614 1615161616171717 181719161915 1814 1714191319121811 1711 ;B IBIIIB121B131B14 16151B161B17 :1
40
2. Block malereien
09 16: 091E : 0926: 092A: 0932: 093A: 0942: 094A:
10 10 IF 24 22 22 25 00
11 15 17 11 13 17 15
10 10 20 23 22 23 25
108 109 110 111 112 113 114 115
HEX HEX HEX HEX HEX HEX HEX HEX
1011101210131014 10151016 10171E17 ;L IFl72017 24 11231122112212 2213221422152216 22 172317241725 16 25 15251425132512 ; 0 ; ENOE 00
Zwei weitere LORES-Routinen haben wir nicht be nötigt:
NEXTCOL $F85F E rhöht die COLOR-Numme r um 3. Ei ngabe: Ausgabe: COLOR-Maske in beiden Nibbles um 3 erhö ht
SCRN $F871 Bestimmt die Farbe eines LORES-Pun ktes X,Y. Eingabe: Akku
= Y , Y-Reg = X
Ausgabe: A kku = Farbnummer des Punktes
41
3. Der kleinkarierte Apfel Der Monitor enthält keine Routinen für die hochaufl ösende Grafik des Apple, so daß wirfür unsere nächsten Versuche fast aussch ließlich auf den Applesoft-Interpreter angewiesen sind. Ein Listing ist von Apple nie veröffentli cht worden , aber freie Autoren haben dies nachgeholt , indem sie den Maschinencode von $DOOO bis $F7FF ana lysierten. In bezug auf die HIRES-Routinen sind alle App lesoft-Interpreter - vom Apple IIplus bis zum He - identisch, so daß die hier aufgeli steten Informationen als "sicher" gelten können. Wir wollen in diesem Buch nicht über die theoretischen und programmierpraktischen Prinzipien der Interpreter-Routinen reden, da all ein die Theorie über das Ziehen einer Diagona len auf einer Rasterseite ein paar Buchseiten füllt . Stattdessen werden wir lernen, die Routinen mit den richtigen Parametern aufzurufen und so alle Applesoft-Befehle auch von der Assemb ler-Ebe ne auszuführen .
3.1 Hilfe, wo steht der Punkt Die hochauflösende Grafik benutzt einen anderen Speicherbereich als di e Textoder LORES-Anzeige. HIRES 1 (HGRl) belegt $2000 bis $3FFF und HlRES 2 (HGR2) benötigt die Speicherplätze von $4000 bis $5FFF für sich. Die hochauflösende Grafik nutzt also zwei RAM-B löcke von je 8 KByte, die heute mitten im Hauptspeicher liegen. Vor einigen Jahren hatte der App le nur 16K RAM, und da lag die Grafik ganz oben. Der Speicher ist heute auf 128K gewachsen, aber da die ROM-Routinen noch immer die selben geblieben sind, müssen wir jetzt unsere Programme um die HIRES-Grafik herumschreiben. Wenn Sie di e Organisation des Textbi ldschirms schon kompliziert fanden, dann werden Sie beim HIRES-Schirm vielleicht ein verzweifeltes Läche ln aufsetzen. Bei näherem Hinsehen sind aber viele Parallelen zum Textbildschirm zu finden , so daß wir auch die HIRES "in den Griff bekommen" .
3. Der kleinkarierte Apfel
42
Der Apple hat ein e Auflösun g vo n 280 * 192 Punkten. Mit der doppelthochauflöse nden Grafik des IIc und des He mit 64k-Karte sind daneben noch 560 * 192 Punkte mögli ch. Wir werden an di eser Stelle aber auf die Doub le-HIRES ni cht weiter eingehen. In der Zeitschrift "Peekel''' sind ei nige Aufsä tze über DoubleHIRES erschienen. Um zu DHGR zu kommen, müssen Sie die fol ge nden Softswitches betätigen: STA STA STA STA STA STA
$C050 $C052 $C057 $COOl $COOD $C05E
TXTCLR MIXCLR HIRES SOSTORE SOCO L DHIRESON
STA C05F DHIRESOFF
Wenn Sie die 192 Punkte , die von 0 bis 191 (= $00 - $BF) gezählt werden , in Gruppen zu je 8 Zeilen aufteilen, erh alten Sie 24 Gruppen. Diese entsprechen den 24 Zeilen des Textbi ldschirms . Wenn Sie die jeweils oberste Lini e als "Grundlini e" beze ichn en, so fo lgen die 7 nächsten Lini en jewe il s mit einer um $0400 höheren Adresse im Speicher (siehe Abb. 4). Während beim LORES aus einer Textzeile zwei Grafikzeilen werden , di e durch die beiden Nibble jedes Bytes adressiert werden, spaltet sich bei der HIRES-Grafik jede Gruppe in 8 Grafikzei len auf, die alle ihre eige nen Speicherplätze besitze n. ________________
~-N~_~~~~~~OO~O~~~_N~~~~~~~~OO~O~~~_N~_~~~ ~~oooooooooooooO
$2000
~
$2060 ~
$2100
$2180
$2200 $2280 $2300 $ 2380 $2028 $20A8 $1128 $21A8
""-..1 11 ""-..1
p.,
1\
1\
1\
-
-
$2000
$noo
$ 2800 $2COO $ 3000 $ 3LOO $ 3800 $ 3COO
S2228
$22A8 $2318 $23A8 $2OS0 $ 2000 $2J1j0
$ 2100 $ 2150 $ 2200 $2350 $ 2300
Abb. 4: Adress ie run g der hochaufl öse nden Grafikseite 1
~NNNNNNN
3.1 Hilfe , wo steht der Punkt
43
Wenn Sie sich jetzt die Gruppen als Textzei len, die die Adresse der Grund linie der Gruppe tragen, vorste llen, so haben Sie den Rest der Orga nisation schon begriffe n. Die Grundlini en lassen sich wiederum in 3 Blöcke unterteil en. Zu Block 1 gehören die Zeilen $00 bis $3F, zu Block 2 di e Zei len $40 bis $7F und zu Block 3 die Zeilen $80 bis $BF. Diese sind den drei Blöcken der Textse ite vergleichbar (siehe Abb. 1). Di e Ze ilen $00, $40 und $80 sind die Grundlini en der Blöcke. Ihre Startadressen si nd $2000, $2028 und $2050 ($4000, $4028 und $4050 für HGR2). Der Abstand vo n $28 Bytes en tspricht ge nau dem Absta nd der Textze ilen 0, 8 und 16, die die Startlin ie n der Textblöcke sind . Die Grundlini en der Gruppen innerhalb eines Blocks sind rege lmäß ig angeordnet und gegenein ander um $80 Bytes versetzt , genau wi e die Textzeilen innerhalb eines Blocks. Die Analogie zum Textbildschirm ge ht so weit, daß auch beim HIRES-Schirm Scratch-Bytes ex istieren. Nur sin d es hi er achtm al so vie le , in sgesamt also 512 Bytes, die nicht angeze igt werden. Sie liegen jeweils "a m Ende" der Zei len im dritten (u nteren) Block . Im norm alen Grafik-B etrieb werde n sie nicht benutzt, stehen uns also als Zwischenspeicher zur Verfügung. Manche Autoren benutzen sie, um zeitweise nicht sichtbare Grafik-Obj ekte dort zu .,parken". Di ese Speicherung ist ni cht dauerhaft , da jeder HG R-B efehl bzw. sein Asse mbler-G egenstü ck auch diese unsichtbaren Bytes mit löscht. Die Scratdl-Bytes sind auch dafür vera ntwortlich, daß Sie ein HGR-Bild nur bis $3FF8 bzw. $5FF8 abzuspeichern brauche n. Ohne Informationsve rlust benötigt das Binärfile un te r DOS 3.3 dann nur noch 33 und nicht mehr 34 Sektoren. Einen Aspekt habe n wir bisher ni cht berücksichtigt : wie liegen die Punkte einer Zeile im Speicher? Zu nächst einmal die gute Nachricht: zu jeder Zeile gehören 40 Bytes , die hin tereinander im Speicher angeordnet sind. Das entspricht dem Textbil dschirm . Zu jedem Punkt auf de m Bil dsch irm gehört 1 Bit im Speicher. E in Punkt ist auf dem Bildsch irm sichtbar (an), wenn das zuge hörige Bit gesetzt (1) ist. Und jetzt die zwei schl echten Nachrichten: 1. Von jedem Byte werden nur die unteren 7 Bits angezeigt. Das Bit 7 (das 8. Bit! ) wird benutzt, um die Fa rbe der übrigen 7 Bits festzulegen. So kommt auch di e horizo ntale Auflös ung von 7 * 40 = 280 Punkte zusta nde. 2. Die Bitnummern im Speicher und auf dem Bildschirm sind genau um gekehrt angeordnet . Während Bit 0 im Speicher ga nz rechts steht. findet sich der zugehörige Punkt ga nz lin ks auf dem Bi ldschirm .
44
3. Der kl einkarierte Apfel
Abb. 5: Zuo rdnung VOll Bitmuster und Bildschirmpunkten
3.2 Was wären wir ohne ROM! Werfen Sie nicht gleich das Handtuch, wen n Sie die HIRES-Organisation nicht sofort verstanden haben. All e notwendigen Funktionen , um jeden HIRESPunkt setzen oder löschen zu können , sind fertig im ROM vorhanden. Zu diesen Routinen gehört ein Satz von Zero-Page-Variablen , die viele Parameter festlegen:
Byte
Funktion
$lA SHAPEL $lB SHAPEH $lCHCOLORl
Lo-Byte des Shapeanfangs Hi-Byte des Shapeanfangs aktive Farbmaske
$26 GBASL $27 GBASH
Lo-Grundadresse einer Grafikzeile Hi-Grundadresse einer Grafikzeile
$30HMASK
Bitmaske für einen Punkt
$EO XOL $El XOH $E2 YO
Lo-Byte der horizontalen Koordinate (XLo) Hi-Byte der horizontalen Koordinate (XHi) vertika le Koordinate (Y)
$E4HCOLORZ $E5HNDX $E6HPAG $E7 SCALEZ $E8 SHAPEPNT $E9 --$EA COLCOUNT
Farbmaske des HCOLOR-Befehls horizontaler Offset (= welches Byte der Zeile) Seitenanzeige ($20 = HGRl, $40 = HGR2) Skalierungsfaktor für Shapes Lo-Byte Zeiger auf Shape-Table-Anfang Hi-Byte Zeiger auf Shape-Table-Anfang Kollisionszähler
3.2 Was wären wir o hne ROM!
45
U m die HGR-Seiten a nzuze igen , müssen Sie ein paar Softswitches betätigen. Die Reihenfolge ist wiederum un erheb lich .
HI RES Seite 1 (HGR1) LDA LDA LDA LDA
TXT CLR MIXCLR LOWSCR HIRES
HIRES Seite 2 (HGR2) LDA LDA LDA LDA
TXTCLR MIXCLR HI SCR HIRES
In beiden Fällen wird der volle Grafik-Schirm ei ngeschaltet. Du rch MIXSET anstelle von MIXCLR können Sie wie bei der LORES-Grafik unte n 4 Textzeile n einbl e nden. Bei HGRI gehören diese zu TEXTI , bei HGR2 zu TEXT2! Dieser "gepokete" Aufruf löscht die vorhandene Grafik nicht. We nn Sie die Grafikse iten mit Löschen aufrufe n wo llen, benutze n Sie die App lesoft-Funktio nen HGR ($F3E2) bzw. HGR2 ($F3D8). HGR setzt die Softswitches für HGRI und gemischten Schirm. Nach HPAG wird $20 geschrieben und die Farbe HCOLORZ wi rd auf $00 (Schwa rz) gesetzt. Der Bere ich vo n $2000 bis $3FFF wird a uf Nu ll gesetzt. HGR2 führt dasse lbe für die zweite Seite aus, nur daß diesmal auf den volle n G rafikschirm geschaltet wird . Wo lle n Sie auc h die Seite 1 ganz sehen, so müssen Sie
JSR HGR STA MIXCLR ausführen.
HGR $F3E2 Wählt HGRl , gemischter Schirm. Löscht den Schirm . Eingabe: Ausgabe: HP AG
= $20,
HCOLORI
= $00
HGR2 $F3D8 Wählt HGR2 , voller Sch irm. Löscht den Schirm. E inga be: A usga be : HPAG
= $40, HCOLORI = $00
46
3. Der kle inka rierte Apfe l
Sie kö nne n die Löschro utine auch separat aufrufe n über HCLR ($F3F2). D urch eine n spätere n E instieg bei BKGND ($F3F6) ist es möglich , den Bildschirm in der gewünschten Farbe e inzufä rben .
HCLR $F3F2 Löscht de n a ktive n HIR ES-Schi rm. E inga be : HPAG = $20 für HGR1 , $40 für HGR2 A usgabe: HCOLOR = $00
BKGND $F3F6 Färbt a kti ve n HIRES-Schirm ein . E inga be : HPAG = $20 für HGR1, $40 für HGR2 HCO LOR1 = gew ünschter Farbcode A usgabe: -
3.3 Eine Linie verschwindet Z ur Fa rbenpracht de r H IRES-Grafik habe ich mich bisher ausgeschwiegen. D as hat seinen guten G rund . Der A ppl e ke nnt 8 Farben. Vier davo n sind paa rweise gle ich : Weiß1 und Weiß2 sowie Schwarz1 und Schwa rz2 . So mit ble iben 6 unterscheidbare Farbe n. Nicht jeder Pun kt ka nn abe r alle 6 Farben ann ehme n. W ie so häufig be i der A pple-Grafik liegen die Verhältnisse ko mplizierte r. Jedes Bit ka nn in e iner vo n zwei Farben erscheine n. D iese Farb en sin d Vio lett oder Bl au , wenn der P un kt eine gerade Spalte nnummer besitzt. Bei e in er ungeraden Spaltennumme r beste ht d ie A uswa hl aus Gr ün und Ora nge. D ie Farben Vio lett und Grün erscheinen , we nn das Farbbit (= B it 7) des Bytes nicht gesetzt (0) ist . Bei gesetzte m Farbbit (1) se hen wir Blau und O range. Eine Zeile beste ht also
3.3 Ei ne Linie verschwindet
47
immer abwechselnd aus violetten und grünen sowie aus blauen und ora nge n Punkten. Nehmen wir zunächst an, das Fa rbbit sei ge löscht. Wenn Sie den Punkt in Spalte oanschalten, erscheint er Violett. Ein Punkt in Spa lte 1 wird Grün wiedergegeben . Wenn Sie gleichzeiti g sowo hl den Pun kt in Spa lte 0 als auch den in Spalte 1 ansch alten , ve rschmelzen diese zu ei ner kurzen horizonta len Linie. die Weiß erschei nt. Allgemein gilt , daß zwe i benachbarte Pu nkte zusammen weiß ergeben. Wenn Sie eine violette Linie zeichnen wo llen, dürfen Sie also nur die Punkte in den geraden Spalten einschalten . Das ist leichter gesagt als getan. Da 7 Punkte zu einem Byte gehören, wechse lt die Anfangsfarbe von Byte zu Byte. Die geradza hligen Bytes beginnen mit Violett, die ungeradza hli ge n dagegen mit Grün. Eine grüne Lini e beginnt mit fo lgendem Pun ktem uster: VGVGVGV
*
*
*
VGVGVGV
GVGVGVG
*
*
*
*
*
*
*
daraus ergeben sich die folgenden Speicherbytes:
o
0 1 0 1 0 1 0 $2A
0101010 1 $55
o
0 1 0 1 0 1 0 $2A
Wie Sie sehen , sind die Bytes nicht identi sch. Das mittlere Byte muß einmal nach rechts ges hiftet (LSR) werden, um den Wert seiner Nachbarn zu erhalten. Wenn Sie das Farb bit unberücksichtigt lasse n, können Sie die beiden Formen durch einfaches Invertieren in ei nander überführen (EOR $7F). Wenn wir die Zeichenroutin en des Applesoft benutzen , wird die Verschiebung vom Programm berechnet . Dies ist auch der Grund für die vielen Bit- und Bytemasken auf der Zero-Page. Da es für jeweils 7 Pun kte nur ein Farbbit gibt , ist die Farbauswahl noch weiter eingeschränkt. So kann es z.B. keine grüne und orange Linie im gleichen Byte geben. Dies Prob lem betrifft beso nders verti kale Linien . Versuchen Sie einm al fo lgendes kurze BASIC-Programm: FARBTEST 10 REM Farbtest 20 HGR2 HCOLOR= 1: REM Grün 30 HPLOT 1 ,0 TO 1 ,19 1 40 GET A$: REM Tastendruck 50 HCOLOR= 5: REM Orange 60 HPLOT 5 ,0 TO 5 , 191 70 GET A$: REM Tastendruck 80 HPLOT 8,0 TO 8,191 90 GET A$: TEXT END
Zunächst wird eine vertikale grün e Linie gezeichn et. Dann fo lgt nach einem Tastendruck daneben eine orange Li ni e. Wenn Sie einen Fa rbm onitor besitzen,
48
3. Der kleinkarierte Apfel
können Sie erkennen , daß dabei die grüne Linie auch orange wird. Besitzer von Schwarz/Weiß-Monitoren kön nen bei gena uem Hinsehen erkenn en, daß die erste Lini e ein klein wenig nach rechts rutscht. Nach einem erneuten Tastendruck sollte eine weitere vertikale Lin ie erscheinen. Sie werden aber vergebli ch auf sie warten: die Linie bleibt verschwunden. Für die erste grüne Linie mußte das jeweilige Farbbit gelöscht sein. Die orange Lin ie benötigt dagegen ein gesetztes Farbbit. Da die Spalten 1 und 5 zum selben Byte gehören, wurde damit auch für die erste Lin ie das Farbbit gesetzt: sie wurde orange. Die dritte Lin ie haben wir in einer geradzahli gen Spalte gezeichnet. Dort sind aber nur die Farben Blau und Vio lett sichtbar. Unsere orange Linie bleibt im Verborgenen. Die gewünschte Farbe eines Punktes oder einer Linie wi rd durch die Speicherste Il e HCOLORZ ($00E4) bestimmt. Um dort das richtige Bitmuster zu setzen , benutzen wir die Routine SETHCOL ($F6EC). Die Farbnum mer wird im X-Register übergeben. Liegt der Wert über 7, wi rd ein "Illegal Quantity Error" ausgegeben. Wenn Sie möchten , können Sie HCOLORZ auch direkt mit einem Farbcode setzen.
HCOLOR Index HCOLOR Farbcode
Farbe
0 1 2 3 4 5 6 7
Schwarz 1 Grü n Vio lett Weiß 1 Schwarz 2 Ora nge Blau Weiß2
$00 $2A $55 $7F $80 $AA $D5 $FF
00000000 00101010 01010101 01111111 10000000 10101010 11010101 11111111
3.4 Wiederaufführung
49
SETHCOL $F6EC Setzt Colo rm as ke für Fa rben 1 bis 7 E ingabe: X-Reg = HCOLOR (1.. 7) Ausgabe: HCOLORZ = Farbcode
3.4 Wiederaufführung Für das Zeichnen von Punkten und einfache n Linienfolgen wollen wir uns noch einmal das Programm "BEISPIEL NR. 3B" auf Seite 18 des ersten Bandes ansehen. Dort wird zunächst di e zweite HIRES-Seite aufgerufe n und ge löscht. Anschließend wird die Farbe Blau direkt gesetzt. Zum Zeichnen von Punkte n und Linien gibt es in A pplesoft nur einen Befehl: HPLOT. In Asse mbl er müssen wir dagegen zwei Routinen benutzen : HPLOT ($F457) und HGLIN ($F53A) . HPLOT setzt einen einzigen Punkt. HGLIN zie ht eine Verbindungsline vom letzten gesetzten Punkt zu ein e m angegebenen E ndpunkt. Das bedeutet, daß vo r dem A ufruf vo n HGLIN wen igste ns einm al auch HPLOT a ufgerufe n werden mußte , da mit ein A nfangsp unkt ex istie rt. Verschiedene HGLIN-Aufrufe können a nschli eßend a nein a nde rge reiht werde n. Unser Beispielprogramm zeichne t ein Rechteck, inde m zunächst ein Eckpunkt mit HPLOT festge legt wird. Von ihm aus werden dann die vie r Seiten gezogen.
50
3. Der kleinkarierte Apfel
HPLOT $F457 Setzt einen Punkt X,Y
Eingabe: HP AG = $20 oder $40, HCOLORZ gesetzt Akku = Y, X-Reg = XLo, Y-Reg = XHi Ausgabe: HCOLORI = Farbmaske GBASLIH ze igt auf Startadresse der zu X, Y ge hörenden Zeile XOLlH, YO Koordinate von X,Y HMASK = Bitmaske , Y-Reg = HNDX = Spaltenindex
HGLIN $F53A
Zieht eine Verbindungslinie zwischen zwei Punkten Eingabe: XOLIH = X-Koordinate des 1. Punktes YO = Y-Koordinate des 1. Punktes HP AG = $20 oder $40 HCOLORZ richtig gesetzt Akku = XLo des 2. Punktes, X-Reg = XHi des 2. Punktes Y-Reg = Y des 2. Punktes Ausgabe: HPAG und HCOLORZ unverändert , HCOLORI gesetzt XOLIH und YO = Koordinaten des 2. Punktes GBASLIH = Startadresse der zu letzt bearbeiteten Ze ile HNDX = Spaltenindex des Endpunktes
Wenn Sie die Zero-Page-Variablen setze n wollen, ohne ein en sichtbaren Punkt zu zeichnen , können Sie das mit HPOS ($F411) tun und damit den (unsichtb aren) HIRES-Cursor positionieren. Mit HFIND ($F5CB) können Sie die internen Cursor-Daten wieder in X- und Y-Werte zurückrechnen.
3.5 E ine Tabelle mit Bilde rn
51
HPOS $F411 Berechnet di e interne n HIRES-Cursor-Werte E ingabe: HP AG = $20 oder $40 , HCOLORZ gesetzt Akku = Y , X-Reg = XLo, Y-Reg = XHi A usgabe: Akku = HCOLORI = Farbmaske GBASLIH zeigt a uf Startad resse de r zu X,Y gehö rende n Zei le XOLlH, YO Koordinaten von X ,Y HMASK = B itmaske , Y-Reg = HNDX = Spaltenindex
HFIND $FSCB Berechnet X,Y aus den internen Cursordaten E inga be: HBASLIH = Zeilenadresse HNDX = Spalten index HMASK = Bitmaske Ausgabe: XOLlXOH = X-Koordinate YO = Y-Koordinate
3.5 Eine Tabelle mit Bildern Einen le tzte n Punkt ha ben wir noch nicht besproche n: die Benutzung von Shapes (Formtabellen) . Vo n Basic aus können Sie durch .,DRA W I AT X ,Y" ganze Linienfolgen auf den HIRES-Schirm bringen. Dazu müssen Sie vorher eine Shapetabelle a nlegen , deren A ufbau im Applesoft-Handbuch beschrieben ist. Sie können diese Technik auch in Asse mbler nutzen. Der BASIC-Befehl "XDRA W" ist ebenfa ll s vor ha nden .
S2
3. Der kleinkarierte Apfel
Sowohl DRA W ($F601) als a uch XDRA W ($F6SD) we rde n in identische r Weise aufge rufe n. Z un ächst muß mit HPOS der interne Cursor auf den Startpunkt der Shape-Zeichnung gesetzt werden. Die Speicherstelle SCALEZ ($00E7) muß gesetzt und der Akk umul ato r mit dem Rotationswert geladen werden. Im X- und Y-Register sind die Startadresse der Shapedefinition (ni cht der Shapetabelle!!) zu übergeben.
DRAW $F601 Zeichnet ein Shape durch OR-Verknüpfung mit de m H intergrund . E inga be: Interne Cursord aten gesetzt (durch HPOS) X-Reg = Lo-Byte des Shapeanfangs Y-Reg = Hi-Byte des Shapea nfa ngs Akku = Rotationswert , SCALEZ = Ska lie run gsfaktor Ausgabe : COLCOUNT = $00 , wenn keine Ko llision mit gesetzten Bits so nst COLCOUNT = Za hl der Ko llisio ne n
XDRAW $F65D Zeichnet ein Shape durch XOR (= EOR)-Verkn üpfung mit dem Hintergrund . E ingabe: Interne Cursordaten gesetzt (durch HPOS) X-Reg = Lo-Byte des Shapea nfa ngs Y-Reg = Hi-Byte des Shapeanfangs Akku = Rotationswert , SCALEZ = Ska li erun gsfakto r A usgabe: COLCOUNT = $00 , wenn keine Ko llision mit gesetzte n Bits sonst COLCOUNT = Zah l der Kollisionen
Di e Routinen DRA W und XDRA W habe n den Nachteil, daß Sie imme r die Anfangsadresse des gewünschte n Shapes wissen müssen . Bei langen Shape-Ta-
3.S Eine Tabelle mit Bildern
S3
bellen müssen Sie dann einen langen Merkzette l auf Ihrem Tisch liege n haben. Viel wahrscheinlicher ist, daß Sie den Beginn der Shape-Tabelle wissen und die Nummer des Shapes in der Tabell e. Im Applesoft-ROM ex istiert zwar ein e Routine , die die Adresse eines Shapes berechnet, wir können sie aber nicht nutze n, da sie versucht , aus einem BASIC-Programm weitere Informationen zu lese n. Ein en Tei l dieser Routine bilden wir deshalb in un seren eige nen Programmen als Unterroutine nach . DRWPARA 1
2 3
4 5 6 7 8
9
0300 0302 0304 0306 0308: 0309: 030B : 030D : 030F : 0311 :
A5 85 A5 85 8A A2 D2 FO 90 4C
0314: 0315: 0317: 0319: 031A: 031B: 031 D: 03 1F : 0320: 0321: 0323: 0325: 0327: 0329:
OA 90 E6 18 A8 BI 65 AA C8 Bl 65 85 86 60
E8 lA E9 IB 00 lA 05 03 99 EI
03 IB lA lA lA E9 IB lA
10 11 12 13 14 15 16 17 18 19 20 21
;************************** DRWPARA * Berechnet die Anfangs- * adresse eines Shapes in * einer bekannten Shape- * ;tabel1e. Dem ROM ent lehnt * Aufruf: SHAPEPNT auf Be-** ginn der Tabelle gesetzt* X-Reg = Shapenummer * ; ************************** SHAPEL SHAPEH SHAPEPNT
EQU $OOlA EQU $OO lB EQU $00E8
ILQERR
EQU $E199 ORG $300
DRWPARA
22
23 24 25 26 27 28 29 30 31 32
NUMOK
33
34 35 36 37 38 39 40 41 42 43 44 45
KLEIN
LDA STA LDA STA TXA LDX CMP BEQ BCC JMP ASL BCC INC CLC TAY LDA ADC TAX INY LDA ADC STA STX RTS
;+$00E9
;nur Beispiel!
SHAPEPNT SHAPEL SHAPEPNT+l SHAPEH UOO (SHAPEL),X ;Maximalzah l NUMOK NUMOK ;( ILQERR ;gibt es nicht KLEIN SHAPEH
; *2 ;S hap e
<
128
;auf Abstandstab. (SHAPEL),Y ;Abstand vom TaSHAPEL ; be l1 enanf. add . ;retten (SHAPEL),Y SHAPEPNT+l ;urspr. Wert SHAPEH SHAPEL
3. Der klein karierte Apfe l
54
Da nach dieser Routin e SHAPELIH schon korrekt gesetzt ist, springen Sie in DRA W bzw. XDRAW etwas später ein. Das Laden von X-und Y-Register entfä llt. DRAWI hat die Adresse $F605 , XDRAWI ist unter $F661 zu erreichen .
3.6 Punkte werden mobil Für viel e Anwend ungen - beso nders für Spi ele - müssen Sie den HIRESSchi rm schnell in alle 4 Richtunge n verschieben. Da dabei immer 8KByte bewegt werden müssen, ist Asse mbler die einzige Sprache, die diese r Aufgabe auf dem Apple gewachsen ist. Das fo lgende Programm ist eine sehr schnell e Routin e, um den gesa mten HIRES-Bi ldsch irm (HGR l ) um ein en Punkt nach rechts , lin ks , oben und unten zu ve rschieben. Außerdem gibt es die Möglichkeit , horizo ntal um 1 Byte (7 Pu nkte) schnell zu verschieben. Für viele Spiele ist das ausreichend, da das auftretende "Rucken" in der schnell en Bewegung meistens untergeht. Die Geschwindigkeit ist nur zu erreichen, inde m die Anfangsad ressen der einzelnen Grafikzei len ei ner Tabell e entnommen we rde n. Ein e Berechnung wäre zu zeitaufwendig. Damit Sie dieses Programm auch von BASIC aus nutzen können, liege n am Anfang feste Sprungadressen zu den einzeln en Unterroutinen , di e Sie mit einem CALL ... anspringen. (TIEF = 36864, HOCH = TIEF+3 , RECHTS = HOCH+3 , LNKS = RECHTS+3 , FR = LNKS+3 , FL = FR+3 ...... CALL TIEF CALL FR usw .) In BASIC müsse n Sie zum Teil andere Namen wäh len, dam it App lesoft darin ke ine rese rvierten Wo rte entdeck t. HIRES-SCROLL 1
2 3 4 5 6 7 8 9
10
;********************************* * HIRES-SCROLL * * * a lle 4 Ri chtun gen * * * um je einen Punkt * * * FAST je 1 Byte * * * * recht s o . links * ********************* * (C ) 1985 Dr. Jürgen B. Kehrel * ;*********************************
11
ORG $9000
12 13
14 15 16 17
18
PTR PTRl
EQU $0000 EQU $0002
Vekto r en zu den ein ze ln e n Routinen
3.6 Punkte werde n mobi l
9000: 9003: 9006: 9009: 900C: 900F':
9012: 9014: 9017: 90 19: 901C: 901E: 901F': 9022: 9024 : 9027: 9029 : 902B: 902D: 902F': 9030: 9032: 9034: 9036: 9038: 903A: 903D: 903E: 9040:
9041 : 9043: 9046: 9048: 904B: 904D: 904E: 9051 : 9053: 9056: 9058 : 905A: 905C 905E 905F' 9061 9063
4C 4C 4C 4C 4C 4C
A2 BD 85 BD 85 E8 BD 85 BD 85 AO BI 91 88 10 EO DO A9 AO 99 88 10 60
A2 BD 85 BD 85 CA BD 85 BD 85 AO BI 91 88 10 EO DO
12 41 70 9F' CB EF'
90 90 90 90 90 90
00 15 91 00 D5 91 01 15 91 02 D5 91 03 27 02 00 F'9 BF' DE 00 27 00 20 F'A
BF' 15 91 00 D5 91 01 15 91 02 D5 91 03 27 02 00 F9 00 DE
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
55 START
JMP JMP JMP JMP JMP JMP
TIEF' HO CH RECHTS LINKS F'ASTR F'ASTL
Verschiebung nach unten oberste Zeile ( $2000ff TIEF' TLI
TL2
TL3
LDX LDA STA LDA STA INX LDA STA LDA STA LDY LDA STA DEY BPL CPX BNE LDA LDY STA DEY BPL RTS
U OO TABLO , X PTR TABHI,X PTR+l TABLO,X PTRI TABHI , X PTRl+l U27 (PTRl) ,Y (PTR), Y TL2 U BF' TLI UOO U27 $2000,Y TL3
löschen :unterste Zeile ;Adresse Lo-Byte ;merke n ;Adresse Hi-Byte ;merken ;Zeile darüber ;Adresse Lo-By te ;merken ;Adresse Hi -Byte ;merken ; $28 (40) Bytes ;Byte l aden ;1 Z. tiefer sp. ;nächstes Byte ;Zeile ferti g? ; alle Z. fertig? ;nein, neue Adr. ;oberste Z. lös chen ;auc h $28 Bytes (40) ;Schle ife ;nächstes Byte ;sind wir ferti g? ;Ja , zurück
Verschiebung nach oben unterste Zeile ($3F'DOff. ) löschen HOCH HLI
HL2
LDX LDA STA LDA STA DEX LDA STA LDA STA LDY LDA STA DEY BPL CPX BNE
UBF' TABLO,X PTR TABHI,X PTR+l TABLO , X PTRI TABHI ,X PTRl+l U27 (PTRl), Y ( PTR), Y HL2 #$00 HLI
;oberste Zeile ;Adre sse Lo-Byt e ;merken ;Adresse Hi-Byte ;merken ;Zeile darunter ;Adresse Lo-Byte ;merken ;Adresse Hi-Byte ;merken ; $28 (40 ) Bytes ;Byte laden und ; 1 Z. höhe r sp. ;nächstes Byte ;Zeile fertig? ;alle Z. fertig? ;Nein, näc hste Z.
56 9065 : 9067: 9069 : 906C : 906D : 906F:
9070: 9072 : 9075 : 9077 : 907A : 907C : 907E : 9080 : 9082 : 9083: 9085: 9087: 9089 : 908B: 908D: 908F: 9090: 9092: 9094: 9095: 9097: 9099: 909A: 909C : 909E:
909F: 90Al: 90A4: 90A6: 90A9: 90AB : 90AD: 90AE : 90BO: 90B2: 90B4: 90B6: 90B7: 90B9 : 90BA:
3. Der kleinkarierte Apfel A9 AO 99 88 10 60
A2 BD 85 BD 85 AO 84 BI OA 24 10 09 85 BO 29 2C 09 91 C8 CO DO E8 EO DO 60
A2 BD 85 BD 85 AO 18 BI 85 90 09 2C 29 4A 24
00 27 DO 3F FA
00 15 91 00 D5 91 01 00 02 00 02 02 01 02 03 7F 80 00 28 E7 CO D4
00 15 91 00 D5 91 01 27 00 02 03 80 7F 02
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
HL3
LDA LDY STA DEY BPL RTS
11'$00 11'$27 $3FDO,Y HL3
;u nt erste Z. l ösc hen ; $28 (40) Bytes ;Sc hleife ; nächstes Byte ; fertig? ;Ja, zurüc k
Verschiebung nach rechts Farbbit bleibt konstant RECHTS RLI
RL2
RL3
RL4
LDX LDA STA LDA STA LDY STY LDA ASL BIT BPL ORA STA BCS AND HEX ORA STA I NY CPY BNE INX CPX BNE RTS
11'$ 00 TABLO ,X PTR TABHI ,X PTR+l 11'$ 00 PTRI ( PTR ), Y PTR I RL3 11'$0 1 PTRI RL4 U7 F 2C 11'$80 (PTR), Y 11'$28 RL2 UCO RLl
; unterste Zeile ;Adresse La-Byte ;merken ;Adresse Hi -Byte ;merken ;:Links beginnen ;Ubertrag löschen ;Byte l aden ;Farbe - ) Carry ;Übertrag? ;Nein ;Ja , einsetzen ; Übertrag merken ;war Farbbit gese tzt ? ;Ne in , Bit7 l ösc hen ;BIT, Trick ;J a, Bit7 setzen ;Byte zurücksp . ;nächstes Byte ; Zeile fertig? ; Nein, weiter ; nächste Zeile ; alle Z. fertig? ;Nein , neue Adresse ;Ja, zurück
Verschiebung nach link s Farbbit bleibt konst a nt LINKS LLI
LL2
LL3
LDX LDA STA LDA STA LDY CLC LDA STA BCC ORA HEX AND LSR BIT
11'$00 TABLO ,X PTR TABHI,X PTR+l 11'$27 (PTR), Y PTRI LL3 U80 2C U7F PTRI
; unterste Zeil e ;Adresse La-Byte ; merken ;Adresse Hi-Byte ;merken ;r.echts beginnen ;Ubertrag l öschen ;Byte l aden ; merken f. Farbbit ;Übertrag vorhanden? ; Ja, einsetzen ;B IT , Trick ;Nein, lösch en ;sc hieben ;war Farbbit ges .?
57
3.6 Punkte werden mob il
90BC: 90BE: 90CO: 90C2: 90C3: 90C5: 90C6: 90C8: 90CA:
90CB: 90CD: 90DO: 90D2: 90D5: 90D7: 90D8: 90DA: 90DC: 90DE : 90EO: 90E2: 90E3: 90E5: 90E6: 90E7: 90E9 : 90EA : 90EC : 90EE:
90EF: 90Fl : 90F4: 90F6: 90F9 : 90FB: 90FC: 90FE: 9100: 9102: 9104: 9106: 9107: 9109: 910B: 910D: 910F: 9110 : 9112 :
10 09 91 88 10 E8 EO DO 60
A2 BC 84 BD 85 C8 84 85 AO BI 91 88 10 C8 98 91 E8 EO 90 60
A2 BC 84 BD 85 C8 84 85 AO BI 91 C8 CO 90 A9 91 E8 EO 90
02 80 00 E9 CO D7
00 15 91 00 D5 91 01 02 03 26 00 02 F9 00 CO DF
00 15 91 00 D5 91 01 02 03 00 02 00 27 F7 00 00 CO DD
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
LL4
BPL ORA STA DEY BPL INX CPX BNE RTS
LL4 U 80 (PTR), Y LL2 U CO LLI
;Nein ; Ja, Bit7 setzen ;Byte zurückschreiben ; näch s tes Byte ;Zei l e fertig? ;nächste Zeile ;al1e Zeilen fertig? ;Nein, we iter ;Ja, zurück
Schnelle Ver sc hiebung nach rechts FASTR FRI
FR2
LDX LDY STY LDA STA INY STY STA LDY LDA STA DEY BPL INY TYA STA INX CPX BLT RTS
U OO TABLO,X PTR TABHI , X PTR+l PTRI PTRl+l U 26 (PTR), Y (PTRl) ,Y FR2 (PTR) , Y UCO FRI
; unterste Zeile ; Adresse La-Byte ;merken ;Adresse Hi-Byte ;merken ; Adresse + 1 ; merken ; Hi-Byte (k Übertr. ) ;va rletzes B. beginnt ; Byte lad en und ;1 Pos. weiter rechts ;näc hstes Byte ; Zeile fertig? ; au f "0" zurück ;Akku auch ;letzes Byte l öschen ;nächste Zeile ;al1e Zeilen fertig? ;Ne in, weiter ;Ja , zurück
Schnelle Verschiebung nach links FASTL FLl
FL2
LDX UOO LDY TABLO,X STY PTR LDA TABHI , X STA PTR+l INY STY PTRI STA PTRl+l LDY UOO LDA (PTRl), Y STA (PTR), Y INY CPY U27 BLT FL2 LDA U OO STA (PTR), Y INX CPX UCO BLT FLI
;unterste Zeile ;Adresse La-Byte ; merken ;Adresse Hi-Byt e ;merken ; Adresse + 1 ; merken ;auch Hi-Byt e ; links beginnen ;Byte l aden und ;1 Pos. nach links ;nächstes Byte ; Zeilenende? ;Nein, we it er ;letzes B. l ösche n näc hste Zeile a lle Zeilen fertig? Nein, weiter
58
3. Der klei nka ri erte Apfel
9114 : 60
9115 : 9110: 9125: 9120: 9135: 913D: 9145: 914D: 9155: 915D : 9165: 9160: 9175: 917D: 9185: 9180: 9195: 9190: 91A5: 91AO: 91B5: 91BO: 91C5: 91CO :
DO 50 DO 50 00 50 00 50 A8 28 A8 28 A8 28 A8 28 80 00 80 00 80 00 80 00
DO 50 00 50 00 50 00 50 A8 28 A8 28 A8 28 A8 28 80 00 80 00 80 00 80 00
DO 50 00 50 00 50 00 50 A8 28 A8 28 A8 28 A8 28 80 00 80 00 80 00 80 00
9105 : 9100: 91E5: 91EO : 91F'5 : 91F'0: 9205: 9200: 9215: 9210: 9225: 9220: 9235 : 9230: 9245 : 9240 : 9255 : 9250 : 9265: 9260 : 9275: 9270: 9285: 928D:
3F' 3F' 3E 3E 3D 3D 3C 3C 3F' 3F' 3E 3E 3D 3D 3C 3C 3F' 3F' 3E 3E 3D 30 3C 3C
3B 3B 3A 3A 39 39 38 38 3B 3B 3A 3A 39 39 38 38 3B 3B 3A 3A 39 39 38 38
37 37 36 36 35 35 34 34 37 37 36 36 35 35 34 34 37 37 36 36 35 35 34 34
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
RTS
;Ja, zurück
Tabe lle der Zeilen adresse n von unten nach oben HGR 1 TABLO
HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX
DODODODODOOOOOOO ; Lo-Bytes 5050505050505050 0000000000000000 5050505050505050 OOOODOOOOOOOOOOO 5050505050505050 OOOODOOOOOOOOOOO 5050505050505050 A8A8A8A8A8A8A8A8 2828282828282828 A8A8A8A8A8A8A8A8 2828282828282828 A8A8A8A8A8A8A8A8 2828282828282828 A8A8A8A8A8A8A8A8 2828282828282828 8080808080808080 0000000000000000 8080808080808080 0000000000000000 8080808080808080 0000000000000000 8080808080808080 0000000000000000
TABHI
HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX
3F'3B37332F'2B2723 ;Hi-Bytes 3F'3B37332F'2B2723 3E3A36322E2A2622 3E3A36322E2A2622 3039353120292521 3039353 12029252 1 3C3834302C282420 3C3834302C282420 3F'3B37332F'2B2723 3F'3B37332F'2B2723 3E3A36322E2A2622 3E3A36322E2A2622 3039353120292521 3039353120292521 3C3834302C282420 3C3834302C282420 3F'3B37332F'2B2723 3F'3B37332F'2B2723 3E3A36322E2A2622 3E3A36322 E2A2622 3039353120292521 3039353120292521 3C3834302C282420 3C3834302C282420
3.6 Punkte we rden mobil
59
Zum Verstehen des Progra mm s ist es nützlich, sich di e Einze lteile mit IDUS anzusehen. Zu den Verschiebu ngen nach oben und unten ist wenig zu sagen, da sie "geradeaus" programmi ert wurden. Die umfangreiche Kommenti erung dürfte Ihnen ausreichende Hinweise geben. Di e schne llen horizontalen Verschiebungen sind ähnlich einfach. Kompliziert wird es bei den Routinen RECHTS und LINKS. Schwierigkeiten bereitet wieder einm al das Farbbit. Wenn Sie einen Punkt auf dem Bildschirm um eine Position nach rechts versetzen, muß er im Byte um eine Position nach links wandern . War er bereits im Bit 6, so darf er nicht nach Bit 7, dem Farbbit , wandern , sondern muß in das Bit 0 des nächsten Bytes ge lange n. Bei einer Verschiebung nach links wiederholt sich dieses gerade andersherum: Bit 0 wa nd ert nach Bit 6 des vo ranstehend en Bytes. Bei Schwarz/Weiß-Bildern ist das Fa rbbit ansonsten nicht weiter problemati sch. Bei einer Farbgrafik jedoch muß es erh alten bleiben . Da das Farbbit für alle 7 Punkte sein es Bytes gilt , kann bei ein er Verschiebung die Farbinformation nicht für all e Punkte erhalten bl eiben. Zumin dest 1 Bit verl äßt das Byte und kommt so unter den Einfluß des benachbarten Farbbits. Di e hier vo rgestellte Lösung hält das Farbbit in seinem jewei lige n Byte ko nstant , während die G rafik- Bits wandern. Fa rbveränderungen sind dabei nicht auszusch ließen. Müssen die Fa rben erhalten bl eiben, so dürfen nur die FASTR- und FASTL-Routinen benutzt werden. Da diese ga nze Bytes verschi eben , bl eibt auch das Fa rbbit immer bei "sein en" Grafik-Bits. Die Programmierung von RECHTS und LINKS mu ß ich Ihnen noch etwas erl äutern , da einige Tricks angewandt wurden, um Platz und Zeit zu spa ren. Der Kopf der Routin e RECHTS arbeitet wie alle and eren. Erst ab Zei le 88 treten Besonderheiten auf. Die Speicherstelle PTRI so ll den beim Verschieben entstehenden Übertrag aufn ehm en, der in das nächste Byte befördert wird . Da beim Start noch kein Übertrag vo rhanden ist, wird er auf Nu ll gesetzt (Z. 88 ,89) . In de r inneren Schleife (RL2) wird das Byte des Bildsch irms geladen und mit ASL nach links geschobe n. Dadurch gelangt das Farb bit in die Carry-Flagge . Anschließend wird PTRI auf einen vorhandenen Übertrag aus dem vorangehenden Byte geprüft. Ist PTRI negativ, so ist ein Übertrag zu berücksichti gen. Bit 0 wird durch "ORA $01" gesetzt. Das entstandene Byte wird nach PTRI gespe ichert , da sich das alte Bit 6 durch ASL jetzt in Bit 7 befindet und in der nächsten Runde das Setzen vo n Bit 0 bewerkstellige n soll. Unser Ca rry-B it enthält imm er noch die Fa rbinform ation. Ist das Carry-B it gelöscht , war das Farbbit O. Mit "AND $7F" wird dieser Zusta nd wiede r hergestellt. War das Carry-Bit gesetzt, muß Bit 7 auch gesetzt werden. Dies geschieht mit "ORA $80" . Danach ist das Byte fertig und kann zurückgeschrieben werden. E in klein er Trick wurde noch angewa ndt. Wenn in Zeil e 96 das Ca rry-Bit gesetzt
60
3. Der kleinkarierte Apfel
ist , ge ht die Befehlsausführung in Zeile 99 weiter. So weit ist das normal. Ist aber das Carry-Bit gelöscht, wird zun ächst in Zei le 97 das "AND $7F" ausgeführt. Jetzt müßte n wir normalerweise das "ORA $80" überspringen , z.B. mit einem "BCC" nach Zeile 100. Stattdessen ste ht ein "HEX 2C" do rt. Auf de n ersten Blick ist das wenig sinnvo ll. Auf den zweite n Blick wird das Geheimnis sichtbar: 2C 09 80 sind die drei aufeinanderfolgenden Bytes. Disassembliert ergibt dieses "BIT $8009" . Der Prozessor "sie ht" dad urch das .,ORA $80" nicht me hr , da es im Operanden des BIT-Befeh ls verschwindet. Der BIT-Befehl ist an di eser Stelle sinnlos, aber ungefährlich. Es ist eine weitverbreitete Praxis , nicht be nötigte 2-Byte Befehle im Operanden von 3-Byte-Befehlen zu maskie re n, z.B. um bei unterschiedlichen E insprungadressen ve rschiede ne Werte zu lade n. Wenn Sie nur 1 Byte mas kie ren müssen , eignet sich "HEX 24" se hr gut dazu. Für den Prozessor li est es sich als "BIT Zeropage" . Der Nachteil di eses Verfahrens wird Ihnen deutlich , wenn Sie so lche Progra mme disassembli eren , ohne über den Quellcode zu verfügen: die TrickstelI e n sind nur schwe r zu entschlüsse ln. Noch ein weiterer geläufiger Trick sei Ihnen verraten: Wenn Sie a m Beginn einer Routine einen E insprun g benötige n, der das Carry-B it setzt , und eine n anderen Einsprung, der das Carry-Bit löscht , kö nne n sie schreiben:
SEC HEX 90
CLC
Einsprung mit SEC Ergibt BCC, wird nie a l s Verzweigung ausgeführt Einsprung mit CLC
D er Wert 90 ergibt zusammen mit dem Opcode für CLC den Befehl BCC 18. Da vorh er das Ca rry-Bit gerade gesetzt wurde , wird die Verzweigung nie ausgeführt , sondern nach de m vermeintlichen Distanzbyte 18 , hinter dem wir das CLC verstecken , weitergemacht. Die Routine LINKS a rbeitet ganz ähnlich wie RECHTS. Da die Verschiebungsrichtung umgeke hrt ist, ä ndert sich die Logik allerdings etwas. Hier wird zunächst das Farbbit (genaugenommen das ganze Byte) nach PTRl gerettet. Dann wird nachgesehe n, ob vom vorange hende n Byte noch ei n Übertrag da ist. Falls ja (Carry gesetzt) , wird Bit 7 auch gesetzt. A nde rnfa lls wird Bit 7 gelöscht. Erst jetzt wird nach rechts geschoben (LSR) . Dadurch kommt u.a. das nach Bit 7 übertragene Bit auf seine n richtigen Platz in Bit 6. Das alte Bit 0 la ndet im Carry-Bit und wird in der nächste Runde berücksichti gt. Z um Abschluß wi rd noch das alte Farbbit (aus PTRl) wi ede r zurückgeholt. RECHTS und LINKS sind wunderschöne Übungsstücke für den Simu lator IDUS. A m besten laden Sie vorher eine Farbgrafik nach HGRl , damit viele unte rschiedliche Bytekombinationen auftauchen. Die Verschi ebung der ga nzen 8KByte dauert allerdings in der Simulation eine .. halbe Ewigkeit" .
61
3.7 Wir "fensterln" ein wenig Fenster sind he utzutage " in ". Da der A ppl e zu einer Zeit entstand , als noch ni emand an die modernen Grafika nsprüche dachte, besitzt er keine Fensterroutinen . Das heißt abe r nicht , daß wir ni cht selber Fenster programmieren können. F ür die "Za uberkü nste" des MAC ist zwar kein Platz im Speicher des A pple II, aber für etwas bescheid enere Ansprüche tut es auch der gute alte lIer noch. Das fo lgende Programm "HGR-Fenster" ermöglicht es Ihnen, auf einer HIRESSe ite beliebig große Fe nster zu öffne n. Dabei dürfen sich maxim al 2 Fe nster auch überlagern , ohne daß die Information im " untere n" Fe nste r verloren geht. Jedes einze lne Fenster kann nach oben gescrollt werde n, um auch längere Textpassage n anzeigen zu könne n. Das Programm ist besonders als Ergänzug zu A pplesoft-P rogram men gedacht , um diese n etwas mehr Pfiff zu verleihen. Es eignet sich besonders gut für Demonstrati ons- und Un terrichtsprogramme. E in klein es BASIC-Programm gibt Ihnen einen Vorgeschm ack , was sich mit "HGRFe nster" alles erreic hen läßt. Das Programm ist eigentlich ein Paket aus selbständigen Routinen, di e alle einzeln aufge rufen werden kö nnen, aber zusam men für die vo llstä ndige Fensterfunktion benötigt werden. Der 1. Teil , "FENSTER", schneidet aus der HIRESSeite Rechtecke heraus , löscht sie und zieht an der Innenkante eine dünne Begrenzungsli nie , um das Fenster besser von der Umgebung abzusetzen . Die 2. Routine ist in der Lage, Rechtecke unabhängig vo n ihrer Umgeb un g zu scrollen. Die einzige E in schrän ku ng li egt darin , daß die Fensterbreite sich imm er mit den Grenzen von ga nzen Bytes decken muß. D ie 3. und 4. Routine dienen schli eßlich dazu , in kürzester Zeit HGR1 nach HGR2 zu kopieren und umgekehrt . Sehen Sie sich zunächst einmal das Demonstrationsprogramm an . Es wird mit "RUN HGR.W .DEMO-STARTER" gestartet. Die Dateien "HGR. WINDOW.DEMO" , "HGR-FENSTER.OBJ" und "HPRINTER .OBJ" müssen sich auf der selben Diskette befinden. Wundern Sie sich nach dem Ende der Demonstration nicht über das Verhalten Ihres Rechners. Sie si nd immer noch auf der HIRES-Grafik, da das Programm "HPRINTER .OBJ" noch aktiv ist. Wir werden es etwas später kennenlernen. Drücken Sie , um wieder auf die normale Textseite zu kommen.
62
3. Der kleinkarierte Apfel
HGR. W.DEMO-STARTER 10 20 30 40 60 70 80
REM **** HGR - WINDOW DEMO **** REM **** (C) 1986 DR. KEHREL **** HOME HTAB 11: INVERSE: PRINT " HGR - WINDOW PRINT CHR$ (4)"BLOAD HGR-WINDOW.OBJ" PRINT CHR$ (4)"BLOAD HPRINTER . OBJ" PRINT CHR$ (4)"RUN HGR.WINDOW.DEMO"
DEMO ": NORMAL
HGR.WINDOW.DEMO 10 20 30 40 50 60 70 80 90 100 105 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300
REM **** HGR - WINDOW DEMO **** REM **** (C) 1986 DR. KEHREL **** HIMEM: 36864: LOMEM: 24576 FENSTER = 36864:SCROLL = FENSTER + 3:COPY21 = SCRO LL + 3 FARBE = 62454 :EI NS = 49236:ZWEI = 49237:SEITE = 230 HT = 4094:VT = HT + 1: REM $FFE,$FFF KOPY12 = COPY21 + 3:YANF = 251 :XANF = 252:XEN = 253: HOEHE = 254 HGR2 : CALL 3819: REM $EEB POKE VT,O: POKE HT,7 PRINT "Wir schreiben jetzt auf HGR2" HCOLOR= 3: HPLOT 0,19 1 TO 40,50 TO 80,191 TO 120,50 TO 160,191 TO 200,50 TO 240,19 1 TO 279 , 50 GOSUB 2000 HPLOT 0 , 0: CALL FARBE GOSUB 2100: GOSUB 2000 CALL FENSTER: POKE 32,6: POKE 33,23: POKE 34,4: POKE 35,8 POKE HT,6: POKE VT , 4: PRINT "Dieses ist e in Fenster.": POKE HT ,6 PRINT "Wi r schreiben Text hin-": POKE HT ,6 PRINT "ein, bi s es voll i st.": GOSUB 2000: CALL SCROLL POKE HT , 6: PRINT "Dann rollen wir einfach";: GOSUB 2000 : CALL SCROLL POKE HT , 6: PRINT "den Ausschnitt hoch!";: GOSUB 2000: CALL SCROLL: CALL SCROLL CALL COPY21: POKE HT,6: PRINT "Es gibt sehr " .. POKE YANF,100: POKE XANF,5: POKE XEN,13: POKE HOEHE ,14 GOSUB 2000 : CALL FENSTER: POKE VT , 13: POKE HT,6: PRINT "kleine"; POKE YANF , 80: POKE XANF,14: POKE XEN,39: POKE HOEHE,lOO CALL FENSTER: POKE HT , 15: PRINT "und sehr grosse Fenster" POKE HT , 15: GOSUB 2000 : PRINT "Mit einem kleinen Trick" POKE HT , 15: PRINT "verschwinden sie wieder ": GOSUB 2000 CALL FENSTER: GOSUB 2000: CALL KOPY12 : GOSUB 2000 : GOSUB 2100: CALL FENSTER HPLOT 0,0: CALL FARBE: GOSUB 2000: HCOLOR= 2: HPLOT 0,0: CALL FARBE GOSUB 2000: CALL FENSTER: POKE VT,4: POKE HT , 6: PRINT "Fuer kleine Demonstra-" POKE HT,6: PRINT "tionen ist das voellig" : POKE HT,6: PRINT "ausreichend." CALL COPY21: POKE YANF,18: POKE XANF,20: POKE XEN,39: POKE HOEHE ,58
63
3.7 Wir "fenster ln" ein we nig
310
GOSUB 2000: CALL FENSTER : POKE VT,3: POKE HT,21: PRINT "Sie koen nen auch " 320 POKE HT ,23: PRINT "zwei Fenster ": POKE HT,23: PRINT "ueberlagern! " 330 GOSUB 2000 : CALL KOPY1 2: GOSUB 2000: GOS UB 2100: CALL FENSTER: GOSUB 2000 340 POKE HT,14: POKE VT,6 : PRINT "E N D E" 350 END 2000 FOR 1 = 1 TO 2000: NEXT I: RETURN REM PAUS E 2100 POKE YANF ,28 : POKE XANF,5 : POKE XEN,30: POKE HOEHE ,38 : RETURN Im BASIC-Programm heißt es "KOPY12" lind "CO PY21" , da Applesoft nur di e ersten zwe i Zeichen beachtet und "COPY12" für Ap pl esoft di e gleich e Variable wie "COPY21 " ist.
HGR-WINDOW 1
2 3 4
5 6 7 8 9
10 11
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
34 35 36
;******************************* (C) 1985
HGR - FENSTER Dr. J ürgen Kehr el
* *
;******************************* HGRI PAGEl HGR2 PAGE2 WNDLFT WNDWDTH WNDTOP WNDBTM BASL BASH BAS2L BAS2H HPAGE BASEADR XHI RE XHILI YENDE YSTART XSTART XENDE YHO EHE
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
HPLOT HGLI N SETHCO L
EQU $F457 EQU $F53A EQU $F6FO
$0006 $0007 $0008 $0009 $0020 $002 1 $0022 $00 23 $004C $004D $002A $002B $00 E6 $OO EB $OO ED $OO EE $OO FA $OO FB $O OFC $OO FD $OO FE
;+$OO EC ;0 - 191 ;0 - 191 ; 0 - 39 !! ; 0 - 39 !! ;0 - 191
ORG $9000 Sprünge zu den einzelnen Rou tinen
64 90 00 : 9003: 9006: 9009:
900C: 900 E: 900 F: 90 10 : 9013: 9015:
9016: 90 18 : 9019: 901A: 901C : 901 E: 9020:
9022: 9023: 9026: 9028: 902A: 902C: 902D : 902F:
3. Der kleinkarierte Apfel 4C 4C 4C 4C
OC B4 2E 4E
90 90 91 91
A5 E6 4A 4A 8D AO 90 DO 01 60
A5 AA 38 65 C9 BO 85
8A 20 A4 A9 91 C8 C4 90
FB FE CO 79 FA
9A 90 FC 00 EB FD F9
9031: E8 9032: E4 FA 9034: 90 EC
9036: A2 03 9038: 20 FO F6
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
JMP JMP JMP JMP
FENSTER HISCROLL COPY21 COPYl2
Modifiziert die Adressenberechnung je nach aktueller HGR-S e ite ($E6) FENSTER
LDA HPAGE LSR LSR STA SEITE+l BNE FNS RTS
;$20 oder $40 ; $08 oder $10 ;ungültig
Zum Beginn des Fenster s (oben) die Fensterhöhe addieren und a l s Endwert des Fensters merken. Muß innerhalb des Bildschirms bleiben «192). FNS
LDA TAX SEC ADC CMP BGE STA
YSTART ;retten YHOEHE n co FNENDE YENDE
; <
192 ??
In der Zeile X die erforder li che Breite l öschen (auf $00 setzen). CLRZEILE
CLRLOOP
TXA J SR LDY LDA STA INY CPY BLT
CALCADR XSTART n oo (BASEADR),Y XENDE CLRLOOP
Nächste Zeile löschen bis ENDE I NX CPX YENDE BLT CLRZEILE Farbe "Weiß" auswäh l en LDX n03 JSR SETHCOL
;Weiß
3.7 Wir "fensterln" ein wenig
903B : 903D: 903F: 9040: 9041 : 9042: 9044: 9045: 9046: 9048: 904A: 904B: 904C: 904E: 9050: 9051 : 9052: 9053:
AO A5 OA OA OA 90 C8 38 E5 BO 88 18 69 90 C8 AA 48 84
00 FC
01 FC 01 01 01
EE
9055: A5 FB 9057: 18 9058: 69 01
905A: 20 57 F4
905D : 905F: 9060: 9062: 9064: 9065: 9066 : 9067: 9069: 906A: 906B: 906D: 906E : 906F: 9071 : 9072: 9074 : 9075: 9076 :
A4 FB
C8 A2 A5 OA OA DA 90 E8 38 E5 08 38 E9 28 BO CA 48 86
00 FD
01 FD 02 01 ED
Aus der X Byte- Position die Bit89 Position für den Rahmen berechnen. 90 X = ( XSTART * 7) + 1 91 92 : Hi-By te X LDY uOO 93 ; Lo-Byte X LDA XSTART 94 ASL 95 ASL 96 97 ASL ;* 8 ;Übertrag? 98 BCC NOINC ;J a INY 99 ;1* abziehen 100 NOINC SEC SBC XSTART 101 ;= * 7 ;Übertrag? 102 BCS NOINCI DEY ;J a. abziehen 103 104 NOINCI CLC ;+ 1 ADC UOl 105 ; Übertrag? 106 BCC NOINC2 ;Ja 107 INY ; Lo-Byte X TAX 108 NOINC2 ;merke n PHA 109 STY XHILI 110 111 112 Y-Wert des Rahmen s festlegen 113 114 LDA YSTART 115 CLC ADC UOl 116 117 1 Punkt oben links se tzen 118 119 JSR HPLOT 120 121 Horiz. Linie nach rechts ziehen 122 123 124 LDY YSTART 125 INY ;X-Hi 126 LDX UOO ;X-Lo LDA XENDE 127 128 ASL 129 ASL 130 ASL ;* 8 ;Übertrag? 131 BCC NOINC3 INX ;Ja 132 ;1 * abziehen 133 NOINC3 SEC 134 SBC XENDE ;= * 7 ;Status retten 135 PHP 136 SEC 137 - 2 SBC U02 138 PLP ;Status zurück ;Übertrag? 139 BCS NOINC4 140 DEX ; Ja 141 NOINC4 PHA ;merken 142 STX XHIRE
65
66
3. Der kleinkarierte Apfel
9078 : 20 3A F5
907B : 907C : 907E : 9080 : 908 1 : 9082 :
9085 : 9087: 9088 : 9089: 908B : 908C : 908D:
9090: 9092: 9093: 9095: 9096:
68 A6 ED A4 FA 88 88 20 3A F5
A4 FA 88 88 A6 EE 68 48 20 3A F5
A6 EE 68 A4 FB C8 20 3A F5
9099: 60
909A: 909B: 909D: 909F: 90Al : 90A3: 90A4 : 90A5: 90A6 : 90A8: 90A9: 90AB : 90AD: 90AE: 90BO: 90B1 : 90B3 :
A8 29 85 09 85 98 OA OA 66 OA 26 66 OA 26 OA 66 60
C7 EB 08 EC
EB EC EB EC EB
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
JSR HGLIN Vert. Linie nach unten PLA LDX XHIRE LDY YENDE DEY DEY JSR HGLIN
;X-Lo
- 2
Horz. Linie nach links LDY YENDE DEY DEY LDX XHILI PLA PHA JSR HGLIN
- 2 ;X- Lo ;und zurück
Kästchen schließen durch vertikal e Linie nach oben zum Anfang LDX XHILI PLA LDY YSTART INY JSR HGLIN Wir sind fertig FNENDE
RTS
Adresse einer Zeile berechnen IN: Akku enthält Zeilennummer (0-191) OUT: (BASEADR) enthält gesuchte Adresse CALCADR SEITE
TAY AND STA ORA STA TYA ASL ASL ROR ASL ROL ROR ASL ROL ASL ROR RTS
HC7 BASEADR H08 BASEADR+l
BASEADR BASEADR+l BASEADR BASEADR+1 BASEADR
;wird "gepoked"
67
3.7 Wir "fenste rln " e in wenig
90B4: A5 22 90B6 : 48 90B7: 20 11 9 1
90BA : 90BC : 90B E: 90CO: 90C2: 90C4: 90C5: 90C6: 90C8 : 90CA: 90CC : 90CD:
A5 85 A5 29 85 68 18 69 C5 BO 48 20
2A 4C 2B E3 4D
90DO : 90 D2: 90 D4: 90D5 : 90D7: 90D9: 90DA:
A2 07 A4 21 88 BI 2A 91 4C 88 10 P9
01 23 22 11 91
90DC : CA 90DD : 30 DB
90 DP: 90 EO: 90 E2 : 90 E4 : 90 E6: 90 E8: 90 EA: 90EC:
18 A5 69 85 A5 69 85 DO
2B 04 2B 4D 04 4D E4
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 23 1 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
;******************* HIRES - SCRO LL * ;******************* Scrollt ein HI RES-Pe ns t er nac h oben Übernimmt Pensterparameter vom normalen Textbildschirm. Es sind immer nur Blöcke vo n 8 * 1 Byte schiebbar. HISCROLL
LDA WNDTOP PHA JSR ADRESSE
Alle "Zeilen" im Penster hoch Eine "Zeile " besteht aus 8 untereinander l iegenden Bytes (HGR-Ze i len) LOOP
LO LI
LDA STA LDA AND STA PLA CLC ADC CMP BGE PHA JSR
BAS2L BASL BAS2H U E3 BASH
LDX LDY DEY LDA STA DEY BPL
U07 WNDWDTH
;Zei l e " jetzt " ; wird Zi el ze il e ;% 11 100011 ;alte Zei l e zurück
UOl WNDBTM CLEAR ADRESSE
;+ 1 ;schon unten? ;Ja, letzte löschen ;merke n ; Basisadresse 8 Bytes
(BAS2L), Y (BASL), Y LI
DEX BMI LOOP Die nächste HGR-Zeile liegt um $0400 Bytes höher im Speicher CLC LDA ADC STA LDA ADC STA BNE
BAS2H U04 BAS2H BASH U04 BASH LO
; immer
68
90EE 90FO 90F2 90F4 90F7. 90F9. 90FB . 90FD. 90FE: 9100: 9102: 9103:
9105: 9107: 9109: 910A: 910C: 910E:
3. Der kleinkarierte Apfel
A5 E9 AO 20 A2 A9 91 C8 C4 90 CA 30
AO A5 18 69 85 DO
23 01 00 11 91 07 00 2A 21 F9 OB
00 2B 04 2B E9
9110 : 60
9111 : 9112 : 9113 : 9115 : 9117: 9119 : 911C: 911D: 911F: 9121 :
4A AA
29 05 85 BD 6A 65 85 60
03 E6 2B 22 91 20 2A
9122: 00 00 00 9126: 50 50 50 912A: AO AO AO
912E : A9 20 9130: 85 07
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
unterste "Zeile" auf Schwarz lö sche n CLEAR
CLO CLl
LDA SBC LDY JSR LDX LDA STA INY CPY BLT DEX BMI
WNDBTM UOl UOO ADRESSE U07 U OO (BAS2L),Y
;8 *
WNDWDTH CLl CLRTS
Adresse der näch ste n HGR-Zeile lie gt um $0400 höher im Speicher LDY LDA CLC ADC STA BNE CLRTS
UOO BAS2H U04 BAS2H CLO
; IMMER ; Fertig
RTS
Berechnet die HGR-Adresse IN : Akku mit Zeil ennummer (0 - 23) OUT (BAS2L) Basisadresse mit berücksichtigtem linken Rand ADRESSE
TAB
LSR TAX AND ORA STA LDA ROR ADC STA RTS
U03 HPAGE BAS2H TAB , X
;HGR-SEITE
WNDLFT BAS2L
HEX 00000000 HEX 50505050 HEX AOAOAOAO
;******************************* Kopiert HGR2 nach HGR 1 * ;******************************* COPY21
LDA U20 STA PAGE1
;$2000
69
3.7 W ir "fe nsterln " ei n weni g 9132: 9133 : 9 135: 9137: 9139: 9 13B : 9 13C: 913 E: 9 140 : 9141: 9143 : 9 145 : 9 147: 9 149 : 914B : 9 14D :
91 4E : 9150: 9152: 9 153 : 9 155: 9 157 : 9 159 : 9 15B : 915C : 915 E : 9160: 9 16 1 : 91 63 : 9165 : 9167: 9169: 916B: 916D:
OA 85 A9 85 85 A8 BI 91 C8 DO E6 E6 A5 C9 90 60
A9 85 OA 85 A9 85 85 A8 BI 91 C8 DO E6 E6 A5 C9 90 60
09 00 06 08 08 06 F9 07 09 09 60 EF
20 07 09 00 06 08 06 08 F9 07 09 09 60 EF
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 34 1 342 343 344 345 346
CLR
ASL STA LDA STA STA TAY LDA STA INY BNE INC I NC LDA CMP BLT RTS
;$4000 PAGE2 #$00 HGRI HGR2 ;Y=O (HGR2 ) ,Y (HGR l ) , Y CLR PAGE 1 PAGE2 PAGE2 #$60 CLR
;weitersetzen ;Ende testen ;weiter
;******************************* Kopiert HGR 1 nach HGR 2 * ;******************************* COPYl2
CLRI
LDA STA ASL STA LDA STA STA TAY LDA STA INY BNE I NC INC LDA CMP BLT RTS
#$20 PAGE 1
; $20 00 ;$4000
PAGE2 #$ 00 HGRI HGR2 ;Y=O ( HGRl ), Y (HGR2), Y CLRI PAGE1 PAGE2 PAGE2 #$ 60 CLRI
;we itersetzen ;Ende testen ; we iter
Die beiden K opi erroutin en sind r echt einfach . Es wer clen j eweils die B ytes der Z ero-Page auf den B eginn des B ildschirm spe icher s ($2000 bzw . $4000) gesetzt un d dann in einer kl ein en inn er en Schl eife , m it den Y -Register als Laufvar iabten , und in ein er großen A ußenschl eife so lange Bytes kop iert (LD A /STA), bis w ir bei der A d resse $6000 angeko mm en und dami t f erti g sin d . Die R o utin e "FENSTER " ist scho n schw ieri ger und auch r echt lang. V ielleicht schreiben Sie ein e kürzer e un d elega nte re Lösung. Da der A uf ru f auch vo n BASI C aus geschehen so ll , bra uchen w ir eine Schni ttstell e zwischen den Progr ammen. Di e Speicher stellen 251 bis 254 ($OOFB bi s $OOFE) di enen uns dazu . 255 w urde ni cht gewählt , da d iese Spe icherstelle bei j edem STR$-Befehl vom
70
3. Der kleinkarierte Apfel
Applesoft-Interpreter benutzt und überschri eben wird. In vie len Büchern ist $OOFF trotzdem fälschlich als frei angegebe n. $OOFA = 250 = YENDE: Y-Wert der Untergrenze (wird berechnet) $OOFB = 251 = YSTART: Y-Wert der Obergrenze (0 - 191) $OOFC = 252 = XST ART: X-Wert der lin ken Grenze (0 - 39) $OOFD = 253 = XENDE: X-Wert der rechten Grenze (0 - 39) $OOFE = 254 = YHOEHE: Höhe des Fensters (0 - 191) Der Wert YENDE wird aus YST ART und YHOEHE berechnet , die übrigen vier Werte müssen vom BASIC-Programm gesetzt werden. Da das Programm sowohl mit HGR1 als auch mit HGR2 laufen soll , wird die Information über die aktive (gewünschte) Seite aus der Spe ich erstell e $00E6 (HPAGE) gewonnen und zur Mod ifikation der Adress-Berechnungsroutine benutzt. CRLZEILE löscht eine Zeile im Fenster, indem die betroffenen Bytes auf $00 besetzt werden. Interessant ist daran die Ad ressbe rechnun g in CALCADR. CALCADR berechnet zu der im Akk u übergebenen Zei lennummer die Basisadresse und legt sie in (BASEADR) ab. Auch hi er lohnt sich eine Untersuchung mit IDUS. In Zeile 184 wird entschieden, um welche HGR-Seite es sich handelt. "ORA $08" berechnet Ad ressen vo n HGRl , .,ORA $10" solche von HGR2. Diese Routine ist kürzer und schnell er als die ROM-Routin e des Applesoft. An die Geschwindigkeit von Tabellen wie im Programm "HIRES-SCROLL" kommt aber auch sie ni cht heran. CALCADR gehört zu jenen Routinen, di e auf Anhi eb nicht zu durchschauen sind. Sie entstand nach und nach , wurde immer weiter optimi ert , bis sie die heutige Fo rm fand. Um sie zu verstehen, müssen wir uns noch einm al mit der Organisation der HIRES-Seite beschäftigen. Die HIRES-Seite läßt sich in 3 Blöcke eintei len. leder Block besteht aus 8 Gruppen, jede Gruppe aus 8 Zeil en . Diese Inform ati on läßt sich in den Bits der Zei lennumm ern wiederfinden. Bit 6 und 7 geben den Block an, Bit 3 - 5 die Gruppe und Bit 0 - 2 di e Zeil e. Wir teilen deshalb das Byte der Zeilen nummer wie folgt auf: B B
G G G
Z Z Z
1 2
1 23
1 23
B steht für Block , G für Gruppe und Z für Zeile. Um jetzt zu r Grund ad resseder zugehörigen Grafikzeile zu kommen , müssen wir di ese Bi ts ein wenig umsortieren. Für das Hi- und das Lo-B yte ergeben sich folgende Verhältn isse:
71
3.7 Wir "fe nste rln " e in wenig
Hi-Byte
- p p Z Z Z GG
1 2312
La-Byte GBBBB312 12-
Bit 5 und 6 vom Hi-Byte (PP) e nth alte n die Info rm atio n über die HGR-Seite.10 steht für Seite 2, ein 01 für Seite 1. Statt de r Striche ist d as betreffende Bit auf Null zu setzen. Versuchen wir a ls Beispiel die Zeile $55 . Wir finden folgende A ufteilung:
B B GGG Z Z Z 1 2
1 23
123
o
0 1 0
1 0 1
1
= $
55
Wenn wir die Adresse für HGR1 ausrechnen wollen, steht 01 für PP. -
Hi-Byte Z Z Z GG
p p
12312
o 0 1 1 0 101 $35
La-Byte GBBBB31212
o 0 1 0 1 0 0 0 $28
A ls Adresse e rgibt sich demnach $3528. Die Routine CALCADR besorgt nun nichts ande res , a ls die Bits entsp reche nd de m o bigen Sche ma umzu verte il e n . Nebe n IDUS he lfe n hie r a uch noch Blatt und Bleistift weiter, wenn Sie in der Simulation verfolgen wo ll e n , wo welches Bit bleibt. Beenden wir unseren Exkurs . Wen n der Fensterbereich gelöscht ist , wird an der Innenseite e ine weiße Lin ie gezoge n. Dazu wird die uns scho n gelä ufi ge Routine HGLIN benutzt. Da die rechte n und linken Fenstergre nze n in "Bytes" und nicht in "Spalten " a ngegeben wurden, muß zu näc hst der Bytewert in di e Spa lte um gerechn e t werde n , indem de r Bytewert mit 7 multipliziert wird. Da es e ine e infache Mu ltiplikation mit 7 ni cht gibt , wird mit 8 multiplizie rt , was durch e infac hes dre ima liges L inksschieben zu bewerkstelligen ist. Ansch ließe nd wird de r Bytewert e inm a l abgezoge n , so daß das Ergebn is e in e M ul tiplikatio n mit 7 ist. Da die Linien innen liegen so ll en , sind noch e inige klei ne Korrekturen nöti g. Der Rest ist e infach. HISCROLL besitzt e in e eige ne Schnittstelle zu m BASIC. Die Fenste rvariabl e n der Textseite die nen zur Übe rga be des Scrollfensters.
72 $0020 $0021 $0022 $0023
3. Der kleinkarierte Apfel 32 33 = 34 = 3S
WNDLFT = Linker Rand (0 - 39) WNDWDTH = Fensterbreite (0 - 39) = WNDTOP = Oberer Rand (0 - 23) = WNDBTM = Unterer Rand (0 - 23)
=
=
=
=
Dieser Programmteil benutzt eine altern ative Form der Adressbestimmung . Die Routin e ADRESSE berechnet die Adresse der Grund lini e einer Gruppe , wenn ihr die Numm er der Gruppe (vergleichbar mit der Textzei lennummer) im Akkumulato r übergeben wird . Hier wird wieder ein e kleine Tabelle benutzt. Di e folgend en 7 Zeilen werden durch Addition vo n $400 zur vo rangehenden Adresse erhalten.
3.8 Zeichnen, ohne gesehen zu werden Die HIRES-ROM-Routinen des Apple sind sowo hl fü r HGR1 als auch für HGR2 ausgelegt. Welche Se ite zu m Pl otte n benutzt wird , legt die Speicherstelle HPAG ($00E6) fest. Der Wert $20 führt elazu , daß HGRl benutzt wird, ein $40 gehört zu HGR2. Wenn Sie $60 eintragen , wird der Speicher von $6000 bis $7FFF benutzt. Dieser Speicherbereich wird deshalb von manchen als HGR3 bezeichnet. Wenn Sie kein DOS im Rechner haben oeler ein in di e LanguageCard ge"move"tes DOS 3.3 benutzen, kön nen Sie mit $80 in HPAG noch den Speicher von $8000 bis $9FFF als HGR4 nutzen. Sowohl HGR3 als auch HGR4 können von der E lektronik des Apple nicht angezeigt werden. Sie müsse n deshalb die beiden imagin ären Seiten HGR3 und HGR4 nach dem Zeichnen in eine der beiden Seiten HGR1 oder HGR2 kopieren. Welche Seite angezeigt wird , hängt nur von der Stellung der Softswitches ab. Daraus folgt, das Zeichnen und Anzeigen zwei un abhängige Prozesse sind. Sie können also z.B. HGR1 anzeigen und gleichzeitig aufHGR2 (oder HGR3 oder HGR4) zeichnen. Werden große Objekte auf dem HIRES-Schirm bewegt, entsteht oft ein augenbelastendes Flimmern , da es eine merklich Zeit braucht , bis das Objekt an seinem alten Ort gelöcht und etwas versetzt am neuen wieder aufgeba ut ist. Die Ausnutzung der verschiedenen HGR-Seiten (Page-Fli pping) ermöglicht eine weitgehende Beruhigung eier Anzeige.
3.9 Punkt , Punkt, Komma , Strich
73
Der Ablauf vollzieht sich dabei nach folgenden Prinzip: 1. Das Objekt wird auf Seite 1 gezeichnet und angezeigt .
2. HPAG wird auf $40 gesetzt und das Obj ekt (un sichtbar) an se iner neuen Position geze ichnet. 3. Mit dem Softswitch HISCR wird HGR2 zur Anzeige gebracht . 4. HP AG wird wieder auf $20 gesetzt, der Bildsch irm (unsichtbar) gelöscht und das Objekt wieder etwas weiter versetzt gezeichnet . 5. Mit dem Softswitch LOWSCR wird HGRl zur Anzeige gebracht. Die Schritte 2 bis 5 wiederho len sich jetzt laufend , bis das Objekt sich ni cht mehr bewegt. Da das Löschen und Neuzeichnen nicht sichtbar und der Seitenwechsel für den Betrachter nicht erkennb ar ist, ergibt sich eine ruhige Bewegun g. Wenn Sie ein Objekt vor einem Hintergrund bewegen wo llen, können Sie diesen Hintergrund ohne das Objekt in HGR3 einm al aufbauen und dann unverändert dort belassen. HGR3 wird mit einer Routine, die wie COPY21 aufgebaut ist , jewe ils in die nicht sichtbare Seite kopiert. Dadurch wird gleichzeitig der Hintergrund neu aufgebaut und das alte Objekt ge löscht. Dieser Vorga ng dauert nicht länger als das reine Löschen einer HIRES-Seite. Wenn Sie mehr über Grafikan im ation wissen möchten, finden Sie in "Bewegte Appl e-G rafik" aus dem Hüthig-Ve rl ag oder in "Apple II Raster Grafik" von Pandabooks (jetzt Ampersa nd) viele Anregungen für Asse mbl er-Programmierer. Zum Abschluß noch ein e Warnung: die HIRES-Routinen prod uzieren mit jedem beliebigen Wert in HPAG Ze ichnunge n im Speicher, nur nicht immer dort , wo Sie es gern e hätten. Benutzen Sie also nur die Werte $20 , $40 , $60 und gegebe nenfalls $80 .
3.9 Punkt, Punkt, Komma, Strich Bei der Fenster-Demonstration haben wir schon Schrift auf der HIRES-Seite erzeugt. Bislang habe ich Ihnen aber noch nicht verraten, wie dies programmiert wurde. Um Buchstaben zu erzeugen , müssen wir die Grafikpunkte des HIRES-Schirms so anordnen, daß sie das Schriftzeichen erkennen lassen. Um die gleiche
74
3. Der kleinkarierte Apfel
Schriftgröße wie im Textmodus zu erzielen, muß ein Zeichen bis zu 8 Punkten hoch sein. Seine Breite darf 1 Byte betragen, also 7 Punkte. Wir sprechen deshalb von einer 7*8 Matrix. Damit benachbarte Zeichen nicht anein anderstoßen , muß auf mindestens einer Seite, möglichst aber auf beiden ein Punkt frei blei ben. Die nutzbare Matrix schränkt sich dadurch auf 5*8 Punkte ein . Da einige Zeichen Unterlängen bes itzen, muß auch nach unten in den meisten Fä llen ein Punkt frei bleibeIl. Um ein Zeichen zu entwerfen, benutzen Sie am besten kariertes Papier. Wir wollen jetzt zusammen ein großes A darste ll en.
Abb. 6: Raste rd a rstellung von " Au
Da das A symm etri sch ist, läßt es sich sehr einfach codieren. Die Spiegelung entfällt hi er, und wenn wir das Fa rbbit auf Null setzen, ergeben sich für die Zeilen folgende Byte-Werte: % % % % % % % %
0 000 1000 0 001 0100 0 010 0010 0010 0010 00111110 0 010 0010 0 010 0010 0 000 0000
= = = =
=
= = =
$08 $1 4 $22 $22 $3E $22 $22 $00
Da es sich bei Buchstaben zumeist um stati sche Objekte handelt , di e nicht auf dem Bi ldschirm hin- und herbewegt werden , können wir eine weitere E igenschaft der Applegrafik ausnutzen. Wen n das Farbbit gesetzt ist , ändert sich nicht nur di e Farbe der Punkte, sie werden auch ein kleines Stück (V, Punktbreite) nach rechts verschoben. Wir nutze n diese Tatsache , um einige Buchstaben etwas abgerundeter erscheinen zu lassen. Das "Au läßt sich wie folgt codieren:
75
3.9 Punkt , Punkt , Komma , Strich % % % % % % % %
0 000 1000 0001 0100 1 001 0010 0 010 0010 0 0111110 0010 0010 0010 0010 0 000 0000
= $08 = $14 = $92 = $22 = $3E = $22 = $22 = $00
Bitte de nke n Sie daran , daß a uf dem B ildschirm die Bits spiege lbildlich erscheine n! A m Ende des Programms .,HIRES-Schriften-Ge ne rator" finde n Sie ein en vo llständigen Zeichensatz, de r a uf diese Weise zustande gekom me n ist. A uf der Begleitdi skette ist er zusä tzli ch noch als separater Fil e "CHAR.SET" e nthalten. A lle Fonts de r "DOS Programmers Too lkit" -Di skette vo n Ap ple können Sie ebe nso benutzen , da sie vom inneren Aufba u he r gleich sind . Der "HIRES-Schriften-Genera tor" enthält in se inem vo rdere n Teil ein Demonstrationsprogra mm , das Ihnen die Benutzung des Ge nerators zeigt. Es stammt aus ein er Testvers io n vo n IDUS , wie sie leicht e rk enne n können. A nschließe nd werde n alle Ausgaben zum Bildschirm über de n Generator a uf die HIRES-Seite umgele nkt werden. Die e rl aubte n Befehle sind im Listing (Zeil e 188ff) a ufgefü hrt.
"PRINTER 1 2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20 21
;******************************* HIRES- Sc hrift e n- Gene rat or * ( C) 1985 Or . Jür gen Keh re 1 * ;******************************* ORG $078 $0 000 $0002 $0004 $0 036 $00 37 $00E6
AOR HGRAOR PTR CSWL CSWH HPAGE
EQU EQU EQU EQU EQU EQU
CONNECT
EQU $03EA
KBO STROBE
EQU $COOO EQU $C010
WAIT HGR2
EQU $F'CA8 EQU $F'308
; Tabe ll e ab $1000
+ $0001 + $0003 + $0005
76
3. Der kleinkarierte Apfel
0078: 08 0079: 20 08 F3
007C: 007E: 0081: 0084: 0086: 0089: 008C: 008E: 0091: 0094: 0097: 0099: 009C: OD9F: 00A2: 00A5 :
00A7: 00A9 : ODAC : OOAE : OOBI : 00B4: 00B6: 00B9: OOBC: OOBE: 00C1 : 00C4 : ODC6: ODC9: OOCC : OOCE: 0001 : OD04: 00D6: ODD8: OOOB: 00F3: 00F4: 00F6: 00F8 : OOFB : OE06:
AO 8C 8C A9 20 8C A2 8E 20 EE A2 8E 20 20 AE 00
A9 80 A9 8D CE A9 20 EE A9 20 EE A9 20 EE A9 20 EE A2 AO 20 C8 00 A2 AO 20 CE 00
00 FE FF AA F6 FE 17 FF F6 FF 27 F'E 2E 2E FF FO
OE FE 05 FF DA C9 2E FF C4 2E FF' 05 2E FF 03 2E DA 08 02 FF F5
OF OF OE OF OF' OE OF' OF OF' OF OF
OF OF OF OF OF' OF OF OF OF' OF' OF OE E5
OF' 05 FF OE 04 C5
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
START
CLO J SR HGR2
;Bi nä rmodus ; HGR2 ini tial .
Rahmen zeichnen
LINIE
LDY STY STY LDA J SR STY LDX STX J SR INC LOX STX JSR JSR LDX BNE
noo
HORZ VERT *"*" STERN HORZ *23 VERT STERN VERT *39 HORZ HPRINT HPRINT VERT LINIE
Titel ausgeben LOA STA LOA STA OEC LDA JSR INC LOA JSR INC LDA JSR INC LDA J SR INC LOX LOY JSR ASC HEX LDX LDY JSR ASC HEX
*14 HORZ *5 VERT INV+l *" I" HPRINT VERT *"0" HPRINT VERT *"U" HPRINT VERT
;Inverse
i 11 S 11
HPRINT INV+l ;Normal *8 *2 STRINGPR "Huethig Software Service " 00 *15 *5 STRI NGPR "NTERAKTIVER " 00
3.9 Punkt, Punkt , Komma , Strich OE07 : OE08: OE09 : OEOC: OE1 3: OE14: OE15: OE16: OE19: OEIB: OEI C: OEID: OEIE: OE21: OE29: OE2A: OE2C: OE2E: OE31: OE3F: OE40: OE42: OE44: OE47: OE61: OE62 : OE64 : OE66 : OE69: OE6F: OE70: OE72: OE74: OE77 : OE94: OE95 : OE97: OE98: OE9B: OEA5:
OEA6: OEA8: OEAA: OEAD: OEBO: OEB2 : OEB5 :
E8 C8 20 C5 00 E8 C8 20 CE 00 E8 C8 20 C9 00 A2 AO 20 B6 00 A2 AO 20 F6 00 A2 AO 20 A8 00 A2 AO 20 A8 00 A2 C8 20 C8 00
A2 A9 20 AD 10 8D 30
FF OE C2 D5
FF OE C4
FF OE CD D5 OD OA FF OE B5 BO 07 OD FF OE EF EE 11 OF FF OE BI B9 06 15 FF OE E3 A9 OF FF OE E5 E9
45 C4 A8 FC 00 CO 05 10 CO 03
OEB7: CA OEB8: DO EE
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 11 6 117 118 119 120 121 122 123 124 125 126 127 128 129 130
77
lNX lNY JSR STRlNGPR ASC "EBUGGER" HEX 00 lNX lNY JSR STRlNGPR ASC "ND" HEX 00 lNX lNY JSR STRlNGPR ASC "lMULATOR" HEX 00 LDX U3 LDY UO JSR STRlNGPR ASC "6502 Prozessor" HEX 00 LDX *7 LDY *13 JSR STRlNGPR ASC "von Dr. Juergen B. KehreI" HEX 00 LDX U7 LDY U5 JSR STRlNGPR ASC " (1985)" HEX 00 LDX *6 LDY *21 JSR STRlNGPR ASC " (c) Dr. Alfred Huethig Verlag" HEX 00 LDX U5 lNY JSR STRlNGPR ASC "Heidelberg " HEX 00 Pause einlegen, bei Tastendruck "sofort" weiter WARTEN
WARTEl
LDX LDA JSR LDA BPL STA BMl
H45 HC4 WAlT KBD WARTEl STROBE ENDE
DEX BNE WARTEN
;Pause
78 131 132 133 OEBA: 20 D8 F'3 134 OEBD: A2 00 135 OEBF' : AO 00 136 OECI : 20 F'F' OE 137 OEC4: CA E5 F'4 138 OEDA: F'7 E5 EE 139 OEEA: 00 140 OEEB: A9 2E 141 OEED: 85 36 142 OEEF': A9 OF' 143 OEF'l : 85 37 144 OEF'3: 4C EA 03 145 146 147 148 149 OEF'6: A2 28 150 OEF'8: 20 2E OF' 151 OEF'B: CA 152 OEF'C: 10 F'A 153 OEF'E : 60 154 155 156 157 OEF'F': 68 158 OF'OO: 85 04 159 0F'02 : 68 160 0F'03: 85 05 161 0F'05: 98 162 0F'06 : 48 163 0F'07: 8E F'E OF' 164 OF'OA: 8C F'F' OF' 165 OF'OD: AO 01 166 OF'OF' : BI 04 167 0F'1l : F'O 06 168 0F'13: 20 2E OF' 169 0F'16: C8 170 0F'17: DO F'6 171 172 0F'19 : 18 173 OF'lA : 98 174 OF'lB : 65 04 175 OF'lD : 85 04 176 0F'lF' : A5 05 177 0F'2l: 69 00 178 0F'23: 85 05 179 0F'25: 68 180 0F'26: A8 181 0F'27: A5 05 182 0F'29: 48 183 0F'2A: A5 04 184
3. Der kleinkarierte Apfel Seite löschen und HPRINT a l s Au sgabeadre ss e eintra gen ENDE
JSR LDX LDY JSR ASC ASC HEX LDA STA LDA STA JMP
HGR2 u OO u OO STRI NGPR "Jetzt ko e nne n Sie ein " "weni g schreiben: " 00 #< HPRINT CSWL #> HPRINT CSWH CONNECT
Ende de r Demonstr a tion STERN STERN 1
LDX #40 JSR HPRINT DEX BPL STERN 1 RTS
Strin gaus gabe ähnli ch Hertzfeld-Routine STRINGPR
SPR
ENDEN
PLA STA PTR PLA STA PTR+l TYA PHA STX HORZ STY VERT LDY U Ol LDA (PTR ) , Y BEQ ENDEN JSR HPRINT INY BNE SPR CLC TYA ADC STA LDA ADC STA PLA TAY LDA PHA LDA
PTR PTR PTR+l u OO PTR+l PTR+l PTR
; imme r
3.9 Punkt, Punkt, Komma , Strich OF2C: 48 OF2D: 60 188 189 190 191 192 193 194 195 196 197 198 OF2E: OF2F : OF30: OF33: OF35: OF38: OF3A: OF3C: OF3E: OF40: OF42: OF44: OF46: OF48: OF4A: OF4C: OF4F: OF52: OF55: OF57: OF59: OF5B: OF5E: OF61: OF64: OF66 : OF68: OF6A: OF6D: OF70: OF71: OF72:
08 48 8C 29 8D C9 FO C9 FO C9 FO C9 FO C9 90 20 EE AD C9 90 A9 8D EE AD C9 90 A9 8D AC 68 28 60
FD 7F FC OD ID OA lE 08 2F OC 49 20 21 9E FE FE 28 14 00 FE FF FF 18 05 00 FF FD
OF73: OF76: OF78: OF7A: OF7D: OF80:
CE 10 A9 8D CE 10
FE OF OF 27 FE OF FF OF 05
OF OF
OF OF OF
OF OF OF
OF OF
185 PHA 186 RTS 187 Ausgabe von ASCII-Zeichen auf dem Grafikschirm als Bitmuster. Jedes Zeichen liegt in einer 8 x 7 Matrix. Bitposition für jedes Zeichen in einer Tabelle entha lt en. Positionierungsroutine rechnet so, daß wie auf dem Textschirm 24 Zeile n a 40 Zeichen ges chrieben werden können. Inver se durch Invertierun g der Bit s. Unter st ützt werden , , und (= HOME). Ein Scroll (Bildschirmro llen ) ist nicht impl ementiert , kann aber ergänzt werden . 199 PHP 200 HPRINT 201 PHA 202 STY YSAVER AND U7F 203 204 STA ASAVER ;CR CMP U OD 205 BEQ CR 206 CMP #$OA ;LF 207 208 BEQ LF CMP #$08 ;BS 209 210 BEQ BS 211 CMP U OC ; FF 212 BEQ FORM 213 CMP #$2 0 ; Leerzeiche n 214 BLT OUT ;CTRL-Zeichen 215 JSR HPRINTER 216 INC HORZ 217 LDA HORZ 218 CMP HO ;Dez ima1! 219 BLT OUT 220 CR LDA *0 221 STA HORZ 222 LF INC VERT 223 LDA VERT 224 ;Dezima1 ! CMP *24 225 BLT OUT 226 LDA *0 227 STA VERT 228 OUT LDY YSAVER 229 PLA 230 PLP 231 RTS 232 233 BS DEC HORZ 234 BPL WEITER 235 LDA *39 236 STA HORZ 237 DEC VERT 238 BPL WEITER
79
80
3. Der kleinkarierte Apfel
OF82: OF84: OF87: OF89: OF8C : OF8F:
A9 8D A9 8D 20 BO
17 FF OF 20 FC OF 9E OF DC
OF91: OF94: OF96: OF99: OF9C:
20 A9 8D 8D FO
D8 F3 00 FF OF FE OF CF
0F'9E: OFAl : OFA2: OFA3 : OFA5: OFA7: OFA9: OFAC: OFAD: OFBO:
OFB2: OFB5: OFB6: OFB8 : OFBA: OFBC: OFBE : OFCO : OFC2: 0F'C4: 0F'C6: OFC8: OFC9 : OFCB : OFCD OFCF' OFDI OFD3
AD 4A A8 29 05 85 B9 6A 6D 85
AD 38 E9 85 A9 85 06 06 26 06 26 18 A9 65 85 A9 65 85
F'F' OF' 03 E6 03 FO OF FE OF 02
FC OF 20 00 00 01 00 00 01 00 01 00 00 00 10 01 01
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
WEITER
FORM
LDA STA LDA STA JSR BGE
#23 VERT U20 ASAVER HPRINTER OUT
; IMMER
JSR LDA STA STA BEQ
HGR2 U OO VERT HORZ OUT
; immer
Vertikale Position (Zeile) in die entsprechende HGR-Adresse umrechnen HPRINTER
LDA LSR TAY AND ORA STA LDA ROR ADC STA
VERT ; merken U 03 HPAGE HGRADR+l LOTAB,Y HORZ HGRADR
; Seite ;Lo aus Tabelle ;Carry hinein ;HTAB dazu
aus dem ASCII-Code des Zeichens seine Position in der Tabelle bestimmen und nach (ADR) speichern. ( POSITION = (ASCII - $20) * 8 ) LDA SEC SBC STA LDA STA ASL ASL ROL ASL ROL CLC LDA ADC STA LDA ADC STA
ASAVER U20 ADR #0 ADR+l ADR ADR ADR+l ADR ADR+l # TABELLE ADR+l ADR+l
'- $20
;* 8 Übertrag berücksichtigen für Hi-Byte
3.9 Pun kt, Punkt, Komma , Strich
OFD5: OFD7: OFD9 : OFDB : OFDD: OFDE : OFDF : OFEl : OFE3 : OFE5 : OFE7: OFE9: OFEB: OFED : OFEF :
AO BI 49 91 C8 18 A5 69 85 A5 69 85 CO 90 60
00 00 00 02 02 FF 02 03 03 03 08 E8
OFFO: 00 00 00 OFF4: 50 50 50 OFF8: AO AO AO
1000: 1008: 1010: 1018: 1020: 1028 : 1030: 1038: 1040: 1048: 1050: 1058: 1060: 1068: 1070: 1078:
00 08 14 28 08 06 04 08 88 84 08 00 00 00 00 00
00 08 14 94 3C 26 OA 08 84 88 2A 08 00 00 00 20
00 08 14 3F OA 10 OA 08 04 10 lC 08 00 00 00 10
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
81
In einer Schleife die 8 Bytes des Zeichens ausgeben. Di e nächste Adresse lie gt um $400 höher als die a lte Adresse. Da auch Y je Byte um 1 ste i gt , wird zur Kompensation nur der Wert $3FF addiert. LOOP INV
LDY LDA EOR STA INY CLC LDA ADC STA LDA ADC STA CPY BLT RTS
lfO
(ADR ), Y ; $7F UOO (HGRADR ), Y
INVERSE
HGRADR U FF HGRADR HGRADR+l U03 HGRADR+1 U08 LOOP
Tabelle für La-Byte der Adresse LOTAB
HEX 00000000 HEX 50505050 HEX AOAOAOAO
ASAVER YSAVER HORZ VERT
DFS DFS DFS DFS
1 1 1 1
ASCII-ZEICHENSATZ TABELLE
HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX
0000000000000000 ; Leerzeichen 0808080808000800 ! 1414140000000000 28943F8A3F850500 $ 083COAIC281E0800 0626100804323000 % 040AOA042A122COO & 0808080000000000 8884040404848800 8488101010888400 082AIC081C2A0800 0008083E08080000 +* 0000000000080804 0000003EOOOOOOOO 0000000000008COO 0020100804020000 /
*
82 1080 1088 1090 1098 10AO: 10A8: 10BO: 10B8: 10CO: 10C8: 10DO: 10D8: 10EO: 10E8: 10F'0 : 10F'8: 1100 : 1108: 1110 : 1118: 1120 : 1128 : 1130 : 1138: 1140 : 1148: 1150 : 1158: 1160 : 1168: 1170 : 1178: 1180 : 1188: 1190 : 1198: 11AO: 11A8: 11BO: 11B8: 11CO: 11C8: 11DO: 11D8: 11EO: 11E8: 11F'0: 11F'8: 1200: 1208: 1210: 1218: 1220: 1228:
3. Der klei nkarierte Apfel
lC 08 lC 3E 10 3E lC 3E lC lC 00 00 10 00 04 lC lC 08 lE lC lE 3E 3E 3C 22 lC 20 22 02 22 22 lC lE lC lE lC 3E 22 22 22 22 22 3E 3E 00 3E 00 00 04 00 02 00 20 00
92 OC 22 90 18 02 82 90 22 22 00 00 08 00 08 22 22 14 22 22 22 02 02 02 22 08 20 12 02 36 22 22 22 22 22 22 08 22 22 22 92 92 90 06 02 30 00 00 08 00 02 00 20 00
32 08 20 10 14 lE 02 10 22 22 8C 8C 04 3E 10 90 2A 92 22 02 22 02 02 02 22 08 20 OA 02 2A 26 22 22 22 22 02 08 22 22 22 14 14 10 06 04 30 08 00 10 lC lE 3C 3C lC
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX
lC92322A26921COO 080C080808081COO lC22201084823EOO 3E90101820221COO 101814123EI0I000 3E021E2020221COO lC82021E22221COO 3E90108808840400 lC22221C22221COO lC22223C20100COO 00008COOO08COOOO 00008COOO08C8884 1008040204081000 00003E003EOOOOOO 0408102010080400 lC22908808000800 lC222A3AlA023COO 081492223E222200 lE22221E22221EOO lC22020202221COO lE22222222221EOO 3E02021E02023EOO 3E02021E02020200 3C02020232223COO 2222223E22222200 lC08080808081COO 2020202020221COO 22120A060A122200 0202020202023EOO 22362A2A22222200 2222262A32222200 lC22222222221COO lE22221E02020200 lC2222222A122COO lE22221EOA122200 lC22021C20221COO 3E08080808080800 2222222222221COO 2222222222140800 2222222A2A362200 2292140814922200 2292140808080800 3E90100804823EOO 3E06060606063EOO 0002040810200000 3E30303030303EOO 0000081422000000 000000000000007F' 0408100000000000 00001C203C223COO 02021E2222221EOO 00003C0202023COO 20203C2222223COO 00001C223E023COO
0 1 2 3 4 5 6 7 8 9
)
? §
A B C D E F' G
H I J K L M N
0 P
Q R S T U V W
X Y Z
Ä Ö Ü
i
a b
c d
e
3.9 Pun kt, Punkt, Komma , Strich 1230: 1238 : 1240 : 1248 : 1250: 1258: 1260: 1268 : 1270: 1278: 1280: 1288: 1290: 1298: 12AO: 12A8: 12BO: 12B8: 12CO: 12C8: 12DO: 12D8: 12EO: 12E8: 12FO: 12F8:
18 00 02 08 10 02 OC 00 00 00 00 00 00 00 04 00 00 00 00 00 00 38 08 OE 00 7F
24 00 02 00 00 02 08 00 00 00 00 00 00 00 04 00 00 00 00 00 00 OC 08 18 2C 7F
04 lC lE OC 18 22 08 36 lE lC lE 3C 3A 3C lE 22 22 22 22 22 3E OC 08 18 lA 7F
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
83 HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX
1824041E04040400 00001C22223C201C 02021E2222222200 08000C0808081COO 100018101010120C 020222 120A162200 OC0808080808 1COO 0000362A2A2A2200 00001E2222222200 00001C2222221COO 00001E22221E0202 00003C22223C2020 00003A0602020200 00003C021C201 EOO 04041E0404241800 0000222222322COO 00002292148C0800 000022222A2A3600 0000221408142200 00002292148C0886 00003EI008043EOO 380COC060COC3800 0808080808080808 OE18183018180EOO 002CIAOOOOOOOOOO 7F7F7F7F7F7F7F7F
f g h i j
k 1 m n 0
P q r
s t u v
w
x Y
z ä
Ö Ü
ß
Block
Das Herz des Programms ist die HPRINT-Routine . Sie kö nnen sie auch ohn e die voranstehenden Te il e als se lbständ iges Programm benu tzen. Der zugehöri ge Zeichensatz darf an be liebiger Stell e im RAM liegen, wenn sein e Startadresse in Zeile 283 (Lo-Byte) und 286 (Hi-Byte) ei nget ragen wird. Dam it Sie HPRINT als Unterroutine ähnlich wie COUT aufrufen könn l' ll . müssen die inn erhalb des Programms benutzten Register (Akk u und Y-Rl'~ I sowie der Prozessorstatus gerettet (Zeil e 200-202) und späte r zurückgehlli l werden (Z. 228-230). Das auszugebende Zeichen wird wie bei COUT im Akkumulator überge ben . Zunächst wird das Bit7 ausgeb lendet und der ASCIICode für die spätere Ausgabe der Bit- Grafik zwischengespeichert. Einige Zeichen, wie z.B. der Rückwärtspfei l, verlangen eine So nderbehandlung. Auf sie wird durch einfache Vergleich e getestet und bei Vo rh andense in in eine Spezialroutine verzweigt . Bei ein em wird die horizonta le Curso rposition (HORZ) auf Nul l gesetzt und die vertikale Position (VERT) um 1 erhöht. Wird dabei die unterste Bildschirmzeile überschritten, wird der Curso r in di e erste Ze ile des Bi ldschirms gese tzt. Ein roll en (SCI'oll ) wie beim Textb ildschirm fi ndet nicht statt. Wenn sie dieses erreichen wollen, müssen Sie nach dem Vergleich (CMP *24) bei Bedarfzu ein er Scroll-Routine verzweigen. Es eignet sich dazu z.B. "HIRES-SCROLL" aus dem Fensterprogra mm.
84
3. Der kleinkarierte Apfel
Bei einem Zeilenvorschub (Line-Feed LF) wird nur der vertikale Cursorwert e rhöht , der horizo ntale bleibt erhalten. E in Rückwärtspfei l (Backspace BS) verringert HORZ um 1. W ird dabei der linke Rand überschritten (HORZ = $FF), dann wird der Cursor in die le tzte Positio n der darüber liegende n Zei le gesetzt. Waren wir schon in der oberste n Zeile , springt der Cursor a n das E nde der unte rsten Zei le. Der Bi ldschirm ist also wie ein e Rolle aufge baut. Ein Seitenvorschub (Form-Feed FF) löscht den Bild schirm und setzt den Cursor an den A nfang der ersten Zeile wie bei eine m HOME des Textbi ldsch irms. Alle übrigen Co ntroll-Zeiche n werden nicht behandelt. Durch den Vergle ich mit dem Leerzeichen ($20), de m druckbaren Zeichen mit dem kle inste n ASCIIWert , werden sie a usgesondert (BLT OUT). Die A usgabe des zum Zeichen gehörenden Bitmusters besorgt die Routine HPRINTER. Jedes Zeichen beansprucht die acht zu eine r G ruppe gehörenden Bi ldschirmze ile n . Desha lb wird zunächst die Adresse der Grundlini e (oben!) berechnet. Dazu dient derse lbe A lgo rithmus wie in HIRES-SCROLL vom Fenste r-P rog ramm. Das Drucken eines Ze ichens beginnt also imm e r von oben. Deshalb si nd auch die Bytes in der Zeichensatz-Tabelle so a ngeordnet , daß das oberste Byte an e rster Stell e steht. Der ASCII-We rt bestimmt die Position eines Zeichens in der Tabe lle . Da das erste Zeichen der Tabelle, das Leerzeichen , bereits den ASCII-Wert $20 besitzt, e rgibt sich die Formel zur Positionsberechnung zu POSITION = (ASCII-Wert - $20) 8. Die Multiplikati on mit 8 rührt vo n der Tatsache her , daß jedes Zeichen 8 Bytes lang ist. Der ASCII-Wert wird aus sein e m Zwischenspeicher zurückgeholt (Z. 271), um dan n um $20 vermindert zu werden. Die Multipli kation mit 8geschi eht durch drei maliges Linksschieben . Nach der ersten Multiplikation mit 2 muß das Ergebn is< 192 sein. Das nächste ASL ka nn bereits das Fassungsvermögen eines Bytes überschreite n , da ein Ergebni s< 384 dabei herausk ommen kann. Deshalb muß ein eventuell sich im Carry-Bit ge bildete r Übert rag mit ROL ADRESSE+ 1 in das H i-Byte gebracht werden. Auch das nächste Lin ksschieben muß jetzt beide Bytes berücksichtigen , da ein Ergebnis< 768 sich ergeben ka nn. U m zu der absoluten Adresse zu gela ngen, wird jetzt noch die Startadresse de r Tabelle addiert. Die Ausgabe der 8 Bytes geschieht in ei ner Schleife, in der das Y-Register als Laufvariable dient . Das Byte wird von der berechn ete n Tabell e npositio n ge laden (Z. 299) und auf die vorher berechnte G rundlini e gesetzt (Z. 301). Das Y-Register wird anschließend um 1 e rhöht , da mit LDA (ADR),Y auf das nächste Byte der Tabelle zeigt. Die Ad resse der nächsten Zeile liegt um jeweils $400 über der vorangegange ne n. Deshalb muß $400 zu (HGRADR) addiert
*
3. 10 De r Kopfsta nd der Bytes
85
werden. Da di e A bspeich e run g a ber mit de r in direkten indizierten Ad ress ie run g durch das Y-Register e rfo lgt , ist eine klein e Korrektur erfo rde rlich: da Y um 1 größer geworde n ist , wird $400 - $1 = $3FF zur alte n A dresse dazugezäh lt. Die Zei le 300 muß ich Ihnen noch erkl ären. So, wie sie jetzt im Programm steht , bewirkt sie nichts. Sie dient led iglich als Platzhalter. Das aufrufende Programm ka nn alle rdin gs de n Operanden von $00 nach $7F verwandeln . Das e ntstehe nde EOR #$7F invertiert das Byte im Akk u (mit A usnah me des Farbbits), bevor es auf de n Bildschirm ausgegeben wird. Dies bewirkt eine inverse Darstellung. Durch das passende setze n dieses Bytes kö nn en sie also zwischen den Attributen Normal und Inverse wechseln . Blinkende Zeiche n sind nur durch stä ndiges Löschen un d Ne uzeichnen zu verwirklichen, eine auch in Asse mbler müh same und aufwendige Methode . Flas h ist deshalb in diesem Programm nicht vorgesehen.
3.10 Der Kopfstand der Bytes Wen n Sie sich viel Mühe gemacht und ein e n eigene n Zeichensatz e ntwo rfe n habe n , we rden Sie sich siche r darüber fre ue n, daß Sie ihn nicht nur für Ihre HIRES-Grafiken benutzen können. Es gibt die Möglichkeit , diesen Ze ichensatz auch auf einen Matrixdrucker zu bringen , ohne daß dieser ein spezielles ladbares Zeiche nsatz-RAM besitzen muß. E in zige Voraussetzung ist die Fähigkeit , ei ne Grafikzei le mit 640 Punkten drucken zu kö nne n. Da sich die verschiedenen Druckerfabrikate in ihrer A nste ue run g unterscheiden, mußte das folgende Progra mm fü r eine n spezie lle n Drucker geschri eben werden. Es läuft un verä nde rt a uf ei ne m EPSON FX-80 und alle n befehlskompatiblen Geräten. A ls Interface die nt ein EPSON Parallel-Interface in Slot 1. Es muß nicht die G rafik-Ve rsion sein . Das NPa ra2 von Brosius & Köhler wurde e be nfalls erfolgreich getestet . Das Programm "HGR-Drucke r" li egt ab $8FOO im RAM des Apple . Darüber ist nach $9300 der Zeichensatz zu laden . Dies kann der Zeichensatz aus Kap itel 3.8 sein , ein selbst e ntworfe ner ode r einer von der "DOS Programmers Toolkit"Diskette. H ie r ist beso nders "COLOSSAL.SET" sehr schö n . Vor dem eigentli chen Program m li egt ein kurzes Startprogramm, daß nur einm al zur Initialisierung benötigt wird und dann überschrieben werde n kan n . Wegen der Art des Aufrufs ist es nur unte r DOS 3.3 und ni cht unte r ProDOS
86
3. Der kleinkarierte Apfel
lauffähi g. Wie Sie das Programm auch unter ProDOS benutzen können , wird später in diesem Band erk lärt. Betrachten wir zunächst die Zei len 28 bis 38. Es wird der Binärmodus hergestellt und dann die Startadresse des eigentlichen Programms ($8FOO) sowohl nach LlNNUM als auch nach CSWLlH geschrieben. Das folgende JSR HIMEMI holt diese Adresse wieder aus LlNNUM und trägt sie sowo hl als HIMEM-Wert für BASIC als auch als TOP OF STRING-Pointer ein. Mehr über diesen letzten Wert erfa hren Sie im Kapitel S. Dadurch wi rd das Maschinenprogramm vor dem Überschreiben durch die Stri ngva ri ab len eines BASIC-Programms geschützt. Zugleich bedeutet es aber auch , daß all e Strin gvariablen gelöscht werden. Sie sollten deshalb "HGR-Drucker" aus ein em BASIC-Programm immer gleich zu Beginn aufrufen , bevor irgendwelche Variablen definiert wurden.
HIMEMI $F28C Setzt neuen HIMEM-Wert , wenn dieser kleiner als der alte ist. Andernfalls erfo lgt ein e Fehlermeldung.
Eingabe: LINNUM ($0050/51) = neuer HIMEM-Wert Ausgabe : HIMEM ($0073/74) und FRETOP ($006F/70) gesetzt
CSW steht für Character Output Switch und bezeichnet ein en Zeiger auf der Nullseite ($0036/37) . Daneben gibt es noch KSW , den Keyboard Switch , zu dem die Adresse $0038/39 gehören. Fast alle Ein- und Ausgaben des Monitors und des BASIC-Interpreters gehen über diese beiden Vektoren. Der erste Befehl vo n COUT lautet z.B .. ,JMP (CSWL)". In CSWLlH steht dann die eigentli che Ausgabeadresse. Durch ein Umsetzen dieser Zeiger hat es Steve Wozniak bei der Konstruktion des Apple möglich gemacht , die Ei n- und Ausgaben umzul enken. Nur dadurch war es z.B . mögli ch, DOS (und ProDOS) in den norm alen Datenverkehr mit einzubeziehen. Ist DOS aktiv, so zeigt CSW nach $9EBD und KSW nach $9E81. Unte r ProDOS lauten die Werte $B84B bzw . $B84E. Das DOS überprüft , ob es sich bei einer Ei n-/Ausgabe um einen DOS-Befehl handelt. Erkennungszeich en bei der Ausgabe ist ein Ctrl-D (CHR$(4)) vor ein em DOS-Befehl , der daraufhin inn erh alb des DOS verarbeitet wird. Handelt es sich um keinen DOS-Befeh l, wird er an die entsprechende Rout in e im Mon itor oder auf einer aktiven Interface-Karte we itergeleitet. Bis zum Ende der Befehlsabarbeitung klinkt sich DOS dabei aus dem Datenverkehr aus, um dann erneut den Vektor in sich se lbst hin ein zu setze n.
3.10 Der Kopfstand der Bytes
87
Woher weiß nun DOS, wem es das Kommando zu übergeben hat? Wenn DOS aktiviert wird (z.B. nach PR *6), rettet es die alten Vektoren und schreibt sie in seine eigenen Ein/ Ausgabevektoren bei $AAS3 bis $AAS6 (DOS 3.3) bzw . $BE30 bis $BE33 (ProDOS). Wenn wir die Ausga be wie in un serem Programm nach START von HGR-Drukker umleiten wollen , damit die Ausgabe un seres Zeich ensatzes auf den Drucker geht , müssen wir die Adresse von START nach CSWLlH schreiben und anschließend DOS von der Änderung informi eren, da das DOS sonst hartnäck ig immer wieder die alte Ad resse zurückträgt. Mit JSR CONNECT über einen Vektor auf Seite 3 ($03EA) geschieht dies bei DOS 3.3, das daraufhin die Adresse von START in sein e eigenen Ausga bevektoren übernimmt. Unter ProDOS geht das ganze etwas anders. Hier muß die Adresse vo n START nach $BE30/31 kopiert werden. (Di e Eingabeadresse von ProDOS ist in $BE32/33 abgelegt) Unser Vorspann-Programm ruft schli eßli ch noch die Routine CLEAR auf, die im Hauptprogramm steht und den Druckpuffer löscht. Nach so lan ge r Vorrede so ll jetzt erst einm al HGR-Drucker folgen.
HGR-DRUCKER 1
2 3 4
5 6 7 8 9
;******************************* HGR-Drucker für EPSON FX-80 Dr. Jürgen B. Kehre1 Heide 1berg, Januar 1986
* * *
;******************************* Version für EPSON Para11 e1Interfac e oder Brosius&Köh1er NPara2 in S10t 1 des App1e
10 11
8EE9: D8 8EEA: A9 00
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
ADRESSE CSWL ACC LI NNUM CONNECT HIMEM1 COUT1 RES TORE SAVE
EQU EQU EQU EQU EQU EQU EQU EQU EQU
$0006 $0036 $0045 $0050 $03EA $F28C $FDFO $FF3F $FF4A
TABELLE READY STROBE
EQU $9300 EQU $C1C1 EQU $C090 ORG $8FOO-$17 CLD LDA t<START
;+$0007
-$95 FF S10t 1 Para11e1interf.
88
3. Der kleink arierte Apfel
8EEC: 8EEE: 8EFO: 8EF2: 8EF4: 8EF6: 8EF9: 8EFC: 8EFF :
85 85 A9 85 85 20 20 20 60
50 36 8F 51 37 8C F2 EA 03 AF 8F
8FOO: 8F03: 8F05: 8F08: 8FOA: 8FOC: 8FOE: 8FIO: 8F12: 8F15: 8Fl7: 8FIA: 8FID:
20 A5 20 29 C9 BO C9 DO 20 A9 20 20 60
4A 45 FO 7F 20 10 OD 08 78 DA D2 3F
8FlE: 8FIF: 8F21: 8F23 : 8F25 : 8F27: 8F29: 8F2B: 8F2D: 8F2F:
38 E9 85 A9 85 06 06 26 06 26
20 06 00 07 06 06 07 06 07
FF FD
8F 8F FF
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
START
FERTI G
STA STA LDA STA STA J SR JSR J SR RTS
LINNUM CSWL #>START LINNUM+l CSWL+l HIMEMl CONNECT CLEAR
JSR LDA J SR AND CMP BGE CMP BNE JSR LDA J SR J SR RTS
SAVE ACC COUTl U7F U20 DRUCKBAR UOD FERTIG PRINT UOA OUTPUT RESTORE
; Reg i ster r etten ;Akku zurückladen ;40Z Bildschi r m ;Bit 7 löschen ; Leerzeichen ; für Druckzeil e ;Re turn ? ; ausge ben ;Gr a fik ze il e ;Zeilenvorschub ; ausgeben ;Registe r zu rück
Po si tion i n der Tabelle be s timmen Leerze i che n i st 1. Zeichen DRUCKBAR
SEC SBC STA LDA STA ASL ASL ROL ASL ROL
U20 ADRESSE UOO ADRESSE+l ADRESSE ADRESSE ADRESSE+l ADRESSE ADRESSE+l
;Druckzeichen im Akku ;ASCII für Leerze i chen ;merke n ;Hi-Byt e auf ; Null setzen ; *2 ( (192) ; *4 ( .(384) ;ev. Ubertrag ;*8 ( .(768) ;ev. Ubertrag
Zum berechneten Grundwert in der Tab e ll e die Anfangsadresse der Tabe ll e add i ere n für die tatsächliche Spe i cherpos iti on
72
8F31: 8F32: 8F34: 8F36 : 8F38: 8F3A: 8F3C:
18 A9 65 85 A9 65 85
00 06 06 93 07 07
73 74 75 76 77
78 79 80 81 82 83 84
CLC LDA ADC STA LDA ADC STA
# TABELLE ADRESSE+l ADRESSf+l
; Lo-By t e ; Hi-Byte
Die 8 Bytes des Zeiche ns in ei nen Zwische nspeicher l aden für die dann fol gende Umcodierung
89
3.10 Der Kopfstand der Bytes 8F3E: 8F40: 8F42 : 8F44: 8F47 : 8F48 :
8F4A: 8F4C: 8F4D: 8F4F: 8F51: 8F54 : 8F55 : 8F56: 8F58: 8F5B: 8F5C: 8F5E:
8F60: 8F63: 8F66: 8F68: 8F6B: 8F6E : 8F70: 8F73 : 8F75: 8F77:
8F78: 8F79: 8F7C : 8F7E: 8F81: 8F84 : 8F86:
AO BI 29 99 88 10
AO 18 A9 A2 7E 6A CA 10 20 88 10 30
8D EE DO EE AD C9 AD E9 BO 60
38 AD E9 8D AD E9 8D
07 06 7F DB 8F F6
07 00 07 DB 8F F9 60 8F EE BA
FF 61 03 62 61 68 62 92 01
61 E8 E6 62 8F E7
FF 8F 8F 8F 8F
8F 8F 8F 8F
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
LADEN
LDY LDA AND STA DEY BPL
U07 ;8 Bytes ( ADRESSE) , Y ;Bit 7 l ösche n U7F ZEICHEN ,Y ;Spe i cher LADEN
;weiter
Di e Bitwerte von horizontaler Anordnung (Bildschirm) umrec hnen in vertikal e Anordnung für de n Matrixdrucker LOOP ROLLEN
LDY CLC LDA LDX ROR ROR DEX BPL JSR DEY BPL BMI
U 07 UOO U07 ZEICHEN ,X ROLLEN ABLAGE LOOP FERTI G
;8 Bit im Byte ;Carry löschen ;Akku initi a li s i eren ;8 Bytes pro Zeiche n ;e ntspr. Bit in ;den Akku rol l en ; a lle Bytes? ;Nein, we it er ;im Puffer able gen ;all e Bits? ;Nei n , we it er ;JA
Umcodierte Bytes in ei nem Zwisc henp uffer merke n , bis e nt weder ein Return fo l gt oder der Puffer voll ist (640 Byt es) ABLAGE
TEST
STA INC BNE INC LDA CMP LDA SBC BGE RTS
$FFFF ; Dummy-Adresse ABLAGE+l ;~o-Byte we it ersetze n ; Ub er tr ag? TEST ;Hi-Byte ebenso ABLAGE+2 ;Pu ffe r-Vo ll t es t e n ABLAGE+l *
Ze il e im Zwischenpuffer ausgebe n Zahl der Ze i chen be reche n , da der Dru cker diese wissen muß PRINT
SEC LDA SBC STA LDA SBC STA
ABLAGE+l *< PUFFER AUSGABE+3 ABLAGE+2 *) PUFFER AUSGABE+4
; Lo-Byte ;Start abziehen ;merke n ; Hi-Byte ; Lä nge in Byte
Druckroutine auf den Startwert setze n
90 8F89 8F8B 8F8E 8F90
8F93: 8F96: 8F99: 8F9C: 8F9E: 8FAl: 8FA4: 8FA7: 8FAA: 8FAD:
3. Der kleinkarierte Apfel A9 8D A9 8D
AD 20 EE DO EE AD CD AD ED 90
E3 94 8F 8F 95 8F
FF D2 94 03 95 94 61 95 62 E4
FF 8F 8F 8F 8F 8F 8F 8F
8FAF: 8FBl: 8FB3: 8FB5: 8FB7 : 8FB9: 8FBB: 8FBD: 8FBF: 8FCO: 8FC2: 8FC4: 8FC5:
A9 85 A9 85 A2 AO A9 91 C8 DO E6 CA DO
68 06 8F 07 03 80 00 06
8FC7: 8FC9: 8FCC: 8FCE: 8FDl:
A9 8D A9 8D 60
E8 61 8F 8F 62 8F
8FD2 8FD5 8FD7 8FDA
FB 07 F6
2C Cl Cl 30 FB 8D 90 CO 60
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
LDA STA LDA STA
; Lo ; Hi
Die Zeichen des Vorspanns und alle ' Zeichen des Zwischenpuffers senden DRUCKEN
TESTI
LDA JSR INC BNE INC LDA CMP LDA SBC BLT
$FFFF OUTPUT DRUCKEN+l TESTI DRUCKEN+2 DRUCKEN+l ABLAGE+l DRUCKEN+2 ABLAGE+2 DRUCKEN
; Dummy-Adresse ; ausgeben ;Lo weitersetzen ;Übertrag? ; Ja, auch Hi ;Zwischenpufferende? ; Lo ;Hi ;no c h kleiner
Zwichenpuffer l öschen und Zeiger (Dummy-Adressen) auf Startwert setzen CLEAR
CLOOP
172
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
* AUSGABE DRUCKEN+2
LDA STA LDA STA LDX LDY LDA STA INY BNE INC DEX BNE
*< PUFFER-$80 ADRESSE *> PUFFER-$80 ADRESSE+l ;auf Startwert *$03 ;Sch leifenzähler *$80 ;Sta rtwert *$00 ;Null zum Löschen (ADRESSE),Y
LDA STA LDA STA RTS
* PUFFER ABLAGE+2
CLOOP ADRESSE+l CLOOP
;Hi-Byte weiter ;Rundenzähler ;Noch nicht fertig ;initialisieren
Zeichen im Akku an den Dru cker ausgeben. Routine ist Slotund Interfaceabhängig ! !! Gi lt für EPSON-Interface in Slot 1 OUTPUT
BIT READY BMI OUTPUT STA STROBE RTS
; Ready? ;Nein ;ausgeben + Strobe ; fertig
191
192 193
Zwischenpei cher für 8 Bytes eines Zeichens
91
3.10 Der Kopfstand der Bytes
8PE3 : IB 2A 04 8PE8: 00
194 195 196 197 198 199 200 201 202
ZEICHEN
DPS 8
Text , der dem Drucker vor j eder Zeil e gesendet we rd en muß . Beim EPSON "ESCAPE , *, 4 , Zeichenzahl in 2 Bytes " für den 8-Nadel Bitmuster-Modu s AUSGABE PUPPER
HEX IB2A04PPPP ;ESC * 4 Dummy HEX 00 ;Puffersta rt
D a mit Sie di eses Programm auch gleich ausp robiere n kö nne n , fo lgt ein kurzes DEMO-Programm. Dazu muß auf der se iben Diske tte der Z eiche nsatz CHAR .SET. OB] vorhande n se in , de n Sie, wen n Sie nicht die Begleitdiskette zu Band 2 geka uft haben , aus dem Programm HIRES-Schriften-Generato r aus Kap itel 3.8 he rausne hme n könne n.
10 20 30 35 40 50
PRINT PRI NT POR I PRINT PRINT END
CHR$ (4)"BLOAD CHAR. SET .OBJ , A$9300" CHR $ (4) "BRUN HGR-DRUCKER.OBJ" = 32 TO 127: PRI NT CHR $ (I) ; : NEXT CHR $ (4)"CATALOG "
Ä nd e rn Sie Z eile 10, we nn Sie ein en a nderen Zeiche nsatz be nutze n wo lle n . Um den Ausgabevektor wieder auf se in en normale n Wert zu setzen , drücke n Sie bitte < RESET> oder . Fa lls Sie eine n etwas sanfte ren Weg , z.B. aus ein e m Programm heraus, vo rzie hen: tragen Sie $FD FO bei CSW ein und rufe n Sie CONNECT auf. Dann ist der 40-Zeichenschirm wieder angekoppelt. War vor her die 80-Zeich e n-Karte a ktiv , so la ute t die Ad resse $C307. Schaue n wir uns wieder ge meinsa m einige Programmteil e an. Das Haup tprogra mm liegt in Zeile 40 bis 52. Von do rt aus werden bei Bedarf andere Programmteile a ufgerufen oder a ngesprun gen . Di e Mo nitor-Routine SA VE rettet alle R egister , den Stackpointer un d den Prozesso rstatus auf di e Zero-Page ab $0045 . R ESTOR E wird sie später wiede r zurückho le n mit A usnahme des Stackpo inte rs, der nicht restauri e rt wird. Di e dazwische nliegende n Z eile n sollte n Sie an den HIRES-Schriften-G enerator e rinn e rn: B it 7 wird gelöscht und dann mit dem Leerzeiche n vergliche n, um Co ntro ll-Zeichen auszuso nde rn. A lle Ze ichen ab de m Leerzeiche n we rden in de r Routin e DRUCKBAR wei te r behandelt. Von den Co ntro ll-Zeichen hat nur noch das eine beso ndere Bedeutung. Es führt zum sofortigen Ausdruck der Druckzeile und einem a nschließenden Zei lenvorschub ($OA = LF) a uf dem Drucker.
92
3. Der kleinkarierte Apfel
SAVE $FF4A Rettet die Prozessor-Register
Eingabe: Ausgabe: $0045 = Akku, $0046 = X-Reg, $0047 = Y-Reg $0048 = Prozessorstatus, $0049 = Stackpointer Setzt Binärmodus (CLD)
RESTORE $FF3F Stellt die Prozessor-Register wi eder her
Eingabe: Ausgabe: Ak ku = $0045, X-Reg = $0046, Y-Reg = $0047 Prozessorstatus = $0048 Der Stackpointer bleibt unverändert!
Auch DRUCKBAR sollte bei Ihnen Erinnerungen wachrufen. Die Zei len 58 bis 79 sind praktisch identisch mit den Zeilen 272 bis 288 des Schriften-Generators. Nun kommt aber Neues hinzu . Die 8 Bytes, die zu dem Zeichen gehören, werden hinterein ander in einen Zwischenspeicher (ZEICHEN) geladen (Z. 85-90). Dabei wird mit AND $7F das Farbb it gelöscht , da es für di e Druckerausgabe nicht gebraucht wird. In den Zeilen 97 bis 107 wird die hori zontale Anordn ung der Bits, di e für die Ausgabe auf den Bildschirm erforderlich ist, in ein e vertikale für den Drucker umgerechnet. Auf dem Bildschirm werden di e Bytes nachein ander von oben nach unten ausgegeben. Der Kopf des Druckers bewegt sich dagegen vertika l über eine Ze ile. Bei einer Bewegun g von links nach rechts muß zunächst das Bit ovon allen 8 Datenbytes zusam mengefaßt ausgegeben werden. Wir fan gen mit Bit 0 an, da wegen der HIRES-Darstellung alle Zeichen spi egelverkeh rt codiert wurden. Als nächstes fo lgen alle Bit 1 usw . bi s Bit 7. Die zwe i Schleifen LOOP (äußere Schleife) und ROLLEN (innere Schleife) besorgen diese Umstellung.
3. 10 Der Ko pfsta nd der Bytes
93
Da beim EPSON das Bit 7 oben gedruckt wird , mü ssen die Bits so in den A kkumul ator gero llt (ROR) werde n, daß als letztes das Bit aus dem ersten Byte hin eingebracht wird. Wir starten deshalb in der inneren Schleife imm er mit X = 7, um mit dem letzten Byte anzufangen. ROR ZEICHEN,X rollt das gewünschte Bit ins Carry-Bit, von wo es mit ROR in den Akk umul ator geschoben und dort gesammelt wird . Sind alle 8.By te durch, wird der Akku, der jetzt ein gültiges Druckerbyte enthält, in einen Druckzwischenspeicher gepackt. Die äußere Schl eife mit dem Y-Register als La ufva ri ablen so rgt dafür , daß alle 8 Bits behandelt werden. Probieren Sie diese Ro utine ruhig mit ein paar Werten im IDUS aus und lasse n sich dabei 6 Bytes von ZEICHEN in der fre ien Anzeige un te n rechts anze igen. 765~3210
oI 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Sp eic her
Bildschirm c:::::)La..I
.....
.........
...
1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 o 0 0 0
0 1 1 1 1 1 0
(',IC""'-ICo-'c::::)c:::::)
c:lu..CCC::CCCr-.C3c::::l
0 0 0 0 0 0 0 0
~
~
1 1 1 1 1 1 1
1 0 0 0 0 0 1
..,..
1 0 0 0 0 0 1
......
~
~
1 0 0 0 7
0 0 0 0 0 1 0 0 0 0
1 1 1 1 1 0
0 0 0 0 0 0
0 0 0 0 0 0
6 5 ~
3
2 1
0 0 0
Orucker Abb. 7: Bitmusterwandlung
Papier
1 1 1 1 1 1 1 0
0 $lE 0
0 0 0 0 0 0
$22 $22 $22
$22 $22 $lE $00
94
3. Der kleink arierte Apfel
ABLA GE speichert das im Akkumul ator übergebene Zeich en im Druckpuffer. Hier werden alle Bytes gesa mmelt , bis eine Druckze ile voll ist oder bis ein < RETURN > erfolgt. In eine Zeil e passen SO Zeichen, die je S Bytes beanspruchen, also in sgesa mt 640 Bytes . Genauso groß ist der Druckspeicher. Die erste Besonderheit di eser Routine ist die Zeile 114, die sogenannten selbstmodifizierenden Code enth ält. Das ist ein Code , der sich während der Laufzeit eines Programms ändert , weil er vom Programm selbst modifiziert wird. Das wäre so , als wenn Sie in ein em BASIC-Programm durch das Programm selbst eine Adresse für einen POKE-Befehl errechnen lassen würden, um sie dann in das laufe nde Programm schreiben und danach ausführen zu lasse n. Di e Adresse für den STA-Befehl wird vom Programm während des Laufs errechn et. Der Wert $FFFF steht nur dort , damit der Assembler beim assembli eren für STA di e abso lute Adressierung berechnet und dann mit den FF FF zwei Bytes im Code freih ält , in di e später di e eigentli che Adresse eingesetzt wird . Wichtig bei jedem selbstmodifizierenden Code ist, daß eier Code initialisiert , d.h. auf seinen Startwert gesetzt werden muß. Dies geschieht erstmals beim Aufruf des Programms durch die Routine CLEA R, di e die Startadresse des Puffers (hi er $SFES) in elen Operanden des ST A einträgt (Zeile 176 bis 179). Die Routine ABLAGE setzt dann se lber bei jedem Aufruf diese Adresse um eins weiter. Irge ndwann ist der Druckpuffer einmal voll. Um dies festzustell en, findet ein Test statt. Wenn di e Abl ageadresse erhöht wo rden ist, wird sie mit der Adresse des Pufferendes verglichen. Ist diese erreicht , wird di e Druckroutine PRINT aufgerufen, die all e 640 Bytes ausgibt. an schließend den Puffer wieder löscht und in Zeile 114 ern eut die Startadresse des Puffers einträgt. Ist das Ende noch nicht erreicht , endet die Routine und das niichste Zeichen kann behandelt werden. Interessa nt ist noch der Vergleich der augenblickli chen Ablageadresse mit der Endadresse. Bei beiden Werten handelt es sich um 2-Byte Zahlen. Durch eine geschickte Kombination von Assembler-Befehlen kann in nur 4 Zeilen festgestellt we rden, ob die erste noch kleiner als di e zweite ist. Dazu wird das Lo-B yte der ersten Zahl in den Akkumul ator geladen, um mit dem Lo-Byte der zweiten Zahl verglich en zu werden. Diese zweite Zahl wird im übri gen vom Assembler errechnet, der durch den Befehl " < PU FFER + $280" zuerst die Länge des Puffers ($280 = 640) zur Startadresse zä hlt und von der Summe nur das Lo-B yte nimmt. War das Lo-Byte von ABLAGE kleiner als das VOll .,ENDE" , ist danach das Carry-Bit gelöscht , an so nsten gesetzt. Jetzt wird das Hi-B yte von ABLAGE geladen und das Hi-Byte vo n "END E" subtrahi ert. Ist vo rh er das Lo-Byte kleiner gewesen , so ist das Carry-B it gelöscht , sodaß zusätzlich eine 1 subtrahiert wird . Im anderen Fall wird kein Übertrag berü cksichti gt. Ist am Ende
3.10 Der Kopfsta nd der Bytes
95
diese r Zeilen das Carry-Bit gesetzt. ist di e erste Zahl gleich groß ode r größer als di e zwe ite. Ist das Ca rry-Bit gelöscht , war die erste Zahl kleiner. Nehmen wir drei Beispiele: di e erste Zahl sei nacheinander $6020, $6030 und $6040 . Die zweite Zahl sei immer $6030. Akku: Ver gl eich mit Carry danach:
$20 $30
$40 $30
$30 $30 1
0
Akku: $60 Subtraktion von $60 Übertrag : 1 Erge bni s: $F'F' Carry danach 0
$60 $60 0 $00
1 $60 $60 0 $00
1
1
Denken Sie dara n, daß der Ü bertrag bei einer Subtrakt ion gleich dem inverti erten Carry-B it ist (Bo rgefl agge !). Die PRINT-Routine berechn et durch Subtraktion des Pufferstarts von der letzten Ablageposition die Anzahl der Zeichen im Puffer, da diese dem Drucker vor dem Ausdruck der Zei le übermittelt werden muß. DRUCKEN enthält se lbstmodifizierende n Code in genau der se iben Art wie ABLAGE. Hi er wird die Initi ali sierun g von den Zeilen 140 bis 143 vorgenommen. Es werden so lange Zeichen aus dem Druckpuffer an den Drucker geschick t, bis all e Bytes gesendet wurden (Vergleich mit ABLAGE) . Dann wi rd der Puffer ge löscht (wir besprechen diesen Teil noch) und der selbst modifizierend e Code von ABLAGE wieder auf den Anfangswert gese tzt. Di e Druckroutin e OUTPUT ist Interface-spezifisch und gilt in di ese r Form nur für die oben gena nnten Karten. Das Byte wird dabe i direkt auf die HardwareAdressen der Interface-Karte geschrieben. Für andere Karten müsse n Sie dort deren Übergabe einsetzen, die Sie in der Betriebsanleitung des Interfaces finden. Unter den folgenden Routinen müßte auch eine für Sie dabei se in , z.B.: OUTPUT
PHA LDY OUTLOOP LDA AND CM P BNE PLA STA RTS
oder
U I0 $C080 , Y *%0000 0111 *%000000010 OUTLOOP $C080,Y
:Akku retten ; Slot 1 ;Status l ade n ;NO PAPER , SELECT und ;ACKNOWLEDGE t esten ;Dru cker nicht bereit ;Zeichen ausgeben ; f e rti g
96 OUTPUT
3. Der kleink ari erte Apfel
BIT BMI STA STA STA RTS
$C09 1 OUTPUT $C09 1 $C092 $C094
; S10t 1 ;z.8 .
C.ITOH 8510A
oder OUTPUT PHA OUTLOOP LDA $C091 AND U10 BNE OUTLOOP PLA STA $C090 RTS
retten S10t 1
; fertig
oder OUTPUT PHA OUTLOOP LDA $C099 AND U70 CMP U10 BNE OUTLOOP PLA STA $C098 RTS
retten *$30 für App1e IIe Super Seria1 Card
Vor dem eigentlichen Druckzwischenspeicher li egt noch ein weiterer kleiner Speicher, der die Werte zur Initialisierung des Druckers aufn imm t. Dem EPSON muß vor jeder Druckzeile fo lgende Seq uenz geschickt werden: ES CAPE 4 (Zeichenanzahl in 2 Bytes). Bei einem anderen Fabrikat müssen Sie diese Werte nach den Angaben im Handbuch anpassen. "ESCAPE 4" steht fes t in diesem Puffer. Die Anzah l der Zeichen kann aber schwanken, da nicht all e Zeil en ganz gefüllt sind. Deshalb stehen auch hier zunächst nur zwei FF FF als Stellvertreter. Vom Programm wird für jede Druckzeile die Byteanzahl eingesetzt (Z. 130-136). In DRUCKEN wird dann dieser Code vor dem Druckzwischenspeicher gesendet. In CLEAR wird der Druckzwischenspeicher auf Null gesetzt und die Anfangsadresse des Puffers wieder nach ABLAGE geschrieben, damit die nächste n Zeichen wieder von vorne beginnend abgelegt werden. An CLEAR können wir se hen, daß es keine allgemeingültigen E mpfehlunge n für kurze und schnelle Assembler-Programme geben kann. Wir haben in diesem Programm an zwei Stell en selbstmodifiz ierenden Code benutzt, um knapp und schnell unser Ziel zu erreichen. Die Aufgabe von CLEAR ist es nun , $280 (= 640) hintereinanderliegende Bytes im Spe icher zu löschen. Die Schwierigkeit li egt darin , daß sich die Anfa ngsad resse erst während der Assemblierung durch
*
*
97
3.10 Der Kopfstand der Bytes
die Länge des bis dorthin stehenden Codes ergibt. Unsere Routine so llte also mit jeder Start adresse laufen. Versuchen wir zunächst eine Lösung mit selbstmodifizierendem Code:
CLEARI 1
2 3 4 5 6 7 8 9
;******************************* Lö schprogramm für $280 Bytes * ;******************************* Variante 1 mit se1bstmodifiziere ndem Code. Zeitbedarf: 16693 Prozessortakte PUFFER
EQU $1234
; willkürlich
10 ORG $300
11
0300 0301 0303 0306: 0308:
08 A9 80 A9 80
34 OE 03 12 OF 03
12 13 14 15 16 17 18 19 20 21
Code initia1isieren START
CLD LDA STA LDA STA
1f PUFFER LÖSCH+2
Löschen
22
030B: A9 00 0300: 80 FF FF
0310: EE OE 03 0313: 00 03 0315: EE OF 03
23 24 25 26 27 28 29 30 31 32
CLEAR LÖSCH
LDA t$00 STA $FFFF
; Dummy
Adresse weitersetzen INC LÖSCH+l BNE TEST INC LÖSCH+2
; Lo ;Übertrag? ;Ja, auch Hi
Bereichsende testen
33
0318: 031B: 031E: 0320: 0323: 0326: 0328:
AD CD 00 AD CD 00 60
OE 29 EB OF 2A E3
0329: B4 14
03 03 03 03
34 35 36 37 38 39 40 41 42
LÖSCH+1 PUFFENDE CLEAR LÖSCH+2 PUFFENDE+1 CLEAR
; Lo-By te ;g1e ich ? ;Nein, weiter ; Hi-By te ;g1eich? ;Nein, weiter ;Ja, Ende
TEST
LDA CMP BNE LDA CMP BNE RTS
PUFFENDE
ADR PUFFER+$280 ;Puffergröße
Zu Demonstrationszwecken wurde der Puffer willkürlich nach $1234 gelegt . Seine Anfangsadresse wird vom Programm in die Zeile 24 geschrieben, bevor die adressierte Speicherstelle auf Nu ll gesetzt wird. Das Weitersetzen der Adresse und die Prüfung , ob das Ende des Puffers erreicht sind, geschehen ganz ähnlich wie in den Zeilen 114 bis 123 des Druckerprogramms.
98
3. Der kleinkarierte Apfel
Das Löschprogramm ar beitet ordentlich. Trotzdem habe ich es nicht benutzt , denn es ist mir zu langsam. Es benötigt 16693 Prozessortakte , um 640 Bytes zu löschen. Es geht viel Zeit damit verloren , daß nach jedem Byte die Adresse mit INe weitergesetzt und anschließend überprüft wird. Zudem geht dabei der Akkumu lator verloren und muß stets mit LDA *$00 neu geladen werden. Der Vorteil dieser Routine ist , daß sie verhältn ismäßig einfach zu ve rstehen ist. Unser zweites Programm benötigt nur noch 7084 Prozessortakte, ist also mehr als doppelt so schnell :
CLEAR2
0300: 0301 : 0303: 0305: 0307: 0309 : 030B: 0300: 030F: 0311 : 0312 : 03 14: 03 16: 0317: 0319:
08 A9 85 A9 85 A2 AO A9 91 C8 00 E6 CA 00 60
B4 06 11 07 03 80 00 06 FB 07 F6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
;******************************* Löschprogramm für $280 Byt es * ;******************************* Variante 2 mit Ausnutzung a ller Regis ter. Laufzeit: 7084 Proze sso rtakte PTR PUFFER
EQU $0 006 EQU $1234
;+$0 007 ; willkür lich
ORG $300 3 Sch l eifendurchgänge. in de nen 1 x $80 und 2 x $100 Byt es ge l ösc ht werden. START
CLEAR
CLO LOA STA LOA STA LOX LOY LOA STA INY BNE INC OEX BNE RTS
*
Dieses Programm ist aus drei Gründen so schnell: 1. Der Akku wird nur einmal auf Null gesetzt 2. Das Lo-Byte wird mit INY hochgezählt und nicht mit INe 3. Die Bereichsüberprüfung geschi eht durch eine Sch leife . Zu Punkt 1 ist wenig zu sagen . Zu Punkt 2: ein "INY" benötigt 2 Prozessortakte , ein " INe abso lut" dagegen 6 Takte . Die Ausnutzung der indirekten indizierten Adressierung (STA O,Y) kostet zwar wieder 2 Takte mehr als ein einfaches
3.10 Der Kopfsta nd der Bytes
99
"ST A a bso lut" , es verble ibe n aber 2 Takte auf der Habenseite. Der entscheidende Punkt ist der dritte: wir nutzen die Ke nntni s aus, daß die ge naue A nzahl der zu löschenden Bytes bekannt und konstant ist. Mit dem X-Register wird eine äuße re Schleife aufgebaut , die dreimal durch laufen wird. Darin eingebettet liegt die innere Schleife, die das Y-Registe r benutzt. Wenn wir nur die Ze il en 25 bis 27 sehen , so erkennen wir , daß das Y -Register bis $FF hochgezählt wird und die damit indizierten Speicherstellen nullgesetzt werden. Wenn wir Y mit $00 beginnen lassen , werden dadurch $100 Bytes ($00 - $FF) gelöscht. A nschließend wird das H i-B yte weitergesetzt, damit der nächste Byteblock gelöscht werden kann. Da die äußere Sch leife dreimal läuft , würden 3 $100 Bytes gelöscht. Wir wollen aber nur $280 Bytes löschen. Wir zerlegen nun $280 in 2 $100 + $80 Bytes. Die 2 $100 Bytes lassen wir "hinten " in der Schleife laufen. Die $80 Bytes erreichen wir, indem wir Y beim ersten Ma l nicht mit $00 starten lasse n, sondern für den ersten Gang durch die äußere Schleife schon auf $80 hoch setzen (Zei le 23). Da die innnere Schleife immer mi t Y = $00 endet, werden anschließend zweimal automatisch $100 Bytes gelöscht. E ine kleine Korre ktur ist noch vo nnöten. Da das Y-Register zu Beginn bereits auf $80 steht , wir aber ab dem ersten Byte unseres Speichers löschen müssen , muß die auf die Nullseiten-Zeiger (PTR) ge legte Zieladresse um diese $80 zu niedrig angegeben werden. Der Assem bl er rechnet in Zeile 18 und 20 die korrigierte Adresse für uns aus . Etwas Nachdenken und die E inbeziehung aller Register des 6502 hat so zu einer sehr kurzen und schnellen Routine geführt , die deshalb auch im Druckerprogramm benutzt wurde.
*
*
*
Die drei verschiedenen Anzeigea rten des App le (Text, LORES und HIRES) haben wir jetzt ausreichend kennengelernt. D iese Kapite l waren nicht ganz ei nfach. We nden wir uns zur Entspannung jetzt den musikalischen Fähigkeiten des Ap ple zu.
100
4. Da steckt MUSIC drin Der ei ngeba ute Lautsprecher des Apple dient nicht nur zu r Erzeugung des nervtötenden "Beep" bei jedem SYNTAX ERROR oder anderen schlimmen Nachrichten. Wir können dem Apple auch angenehm ere Tö ne entlocken. Verglichen mit anderen Rechnern , die zum Teil eigene Schaltkreise für di e Tonerzeugung über mehrere Oktaven besitzen, steht der Apple ziemlich nack t da. Wie wi r schon im ersten Band gesehen haben, besteht di e einzige Möglichkeit zur La utäußerung darin , daß der Prozessor die Speicherstelle $C030 li est oder irgendetwas dort hineinschreibt. Die richtige Anzahl von erzeugten "Klicks" un d ih r zeitlicher Abstand erzeugen einen hörbaren Ton, der uns mehr oder zumeist minder musikalisch erscheint . Di e Höhe eines To nes hängt von der Anzahl der Schwingungen pro Sekunde ab. Der Kammerton A hat z.B . 440 Schwingun gen pro Se kunde ode r 440 Hz. Je mehr Schwingungen pro Sekunde erfo lgen, desto höher ist der erzeugte Ton. Da ein e Schleife in Assembler se hr schnell ist, kö nnen wir sehr hohe Tö ne erzeugen, genau genommen soga r zu hohe. Die absolut kürzeste Form 0300 : LDA $C030 0303: JMP $0300
benötigt 7 Prozessortakte. Da ca. 1 Milli on Takte pro Se kun de möglich sind , kommen wir auf ca . 142000 Schaltvorgä nge in der Sek unde. So schnell kann sich die Membran des Lautsprechers nicht bewegen. Außerde m liegt die To nhöhe in einem Bereich, der höchstens noch Flederm äusen zugä nglich ist. Die Hörgrenze des Menschen li egt in jungen Jahren bei ca . 20000 Schwingungen/Se kunde . Um in den hörbaren Bereich zu gelangen, müsse n wir also Warteschl eife n einbauen. Die "Tasten-Musik" aus Ba nd 1 ist ein Beispiel für die Programmierung so lcher Ve rzögerungen. We nn wir unser Assembler-Programm in Appl esoft BASIC umsetzen, erhalten wir 10 A = PEEK (49200 ) 20 GO TO 10
101
4. Da steck t MUSIC dr in
Der resulti e re nde Ton li egt mit ca. 70 Schwin gungen/Se kunde im Baßbereich. BASIC ist daher fü r Musikprogramme denkbar ungeeign et. Der A usweg aus dem Geschwindigkeitsprob le m findet sich in einer Asse mbler-Ro utin e, di e wir auch von BASIC aus a ufr ufen kö nn e n. Nur di e Wenigsten wisse n , daß der Ap pl e übe r ein ein gebautes Asse mbler-P rogramm zur Musike rze ugung ve rfügt, das von Gary Sha nno n sta mmt. Es ist Bestand te il des .,PROGRAMMERS AID NO.l" ROMs. D ieses sta mmt noch aus de n Zeiten des "INTEGER BASIC" und ist he ute als ROM in keinem Ap ple me hr enthal te n . Aber jeder Fi le ,.INTBASIC" auf der DOS 3.3 Sytem Master Diskette e nthält auch das komplette " PROG RAMMERS AID", das bei jedem "LOADING INTEGER INTO LANGUAGE CARD" mit ins RAM gelangt, wenn Sie über we nigstens 64K Speicher verfügen . Die Dokumentation über INTEGER BASIC und das PROGRAMMERS AID wird von Apple für heutige Rechner nich t mehr mitgeliefert (überhaupt steht in de n bunter we rden den Heftchen immer weniger drin) . Für alle, die dieses Musikp rogramm benutzen wollen , habe ich es disassembliert und a nalysie rt. Sie können es auch im no rmalen RAM-Bereich laufe n lassen , we nn Sie über keine Language-Card (16K-Ka rte) verfügen ode r diese durch ProDOS belegt ist. Zusammen mit ProDOS kö nnen Sie INTBASIC nicht benutzen , da a uch ProDOS die Language-Ca rd für sich be nötigt. U nter ProDOS so llte n Sie das Programm abe r in ein en geschützte n Speicherbereicb lade n , wie clas in Kap itel 10 erklärt ist.
MUSIC
1
2 3 4 5 6
7 8
;******************************* ; MUSIC Programmers Aid No. #1 * ; "Integer-ROM" $0717 - $D7F'B * ;******************************* Analysiert von Dr. Jürgen B. Kehrel F'ür Verwendung ohne Lan guage- Card umgeschrieben auf norma l en RAM-Bereich
9
10 ORG $9517
11
12 13
;38167
Zero-Page Zähler
14
15 16 17 18 19 20 21 22 23 24 25
AB AUF' LÄNGE
EQU $00 EQU $01 EQU $02
; Parameterübergabe KLANG DAUER F'ARBE
EQU $02 F'D EQU $02F'E EQU $02F'F'
; I/O-Bereich
; $02, $03
102
4. Da steckt MUSIC drin
95 17: 4C 4E 95 951A: 951C: 951F: 9521: 9523: 9525: 9527: 9528: 9529: 952C: 952D: 952F: 9532:
A4 AD E6 DO E6 DO 60 EA 4C 88 FO 4C DO
01 30 CO 02 05 03 05
9534: 9536: 9539: 953B: 953D: 953F: 9541: 9542: 9543: 9546: 9547: 9549: 954C:
A4 AD E6 DO E6 DO 60 EA 4C 88 FO 4C DO
00 30 CO 02 05 03 05
954E: 9551: 9552: 9553: 9556: 9558: 955B: 955C: 955E: 9560: 9562: 9565: 9566: 9568:
AD OA A8 B9 85 AD 4A FO 46 DO B9 38 E5 85
2C 95 05 32 95 EB
46 95 Dl 4C 95 EB
FF 02 96 95 00 FD 02 04 00 F9 96 95 00 01
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
SPKR
EQU $C030
Spielt Note . Zyklus- Daten in "AUF" und "AB". Zyklusdauer in "LÄNGE". Zyklus zweigeteilt. START
JMP SUCHE
;Best. Zyklus-Werte
HO CH
LDY LDA INC BNE INC BNE RTS NOP JMP DEY BEQ JMP BNE
AUF SPKR LÄNGE HOCH3 LÄNGE+l HOCH4
; Pulsbr. "aufwärts" ; Lautsprecher ; Zyklusdauer ;noch ni cht zu Ende ;Zyklusdauer ;verringere Pulsbr. ; Zyk lu s abge l aufe n 5 Proz essortak te Zeitverzögerung ;verringere Pulsbr. ; Breite 0, "abwärts" we ite re 6 Pro zessortakte Zeitverz.
LDY LDA INC BNE INC BNE RTS NOP JMP DEY BEQ JMP BNE
AB SPKR LÄNGE RUNTER2 LÄNGE+l RUNTER3
HO CH2
HOCH3 HOCH4 HOCH5 RUNTER RUNTERI
RUNTER2 RUNTER3 RUNTER4
HOCH4 RUNTER HOCH5 HOCH2
RUNTER3 HOCH RUNTER4 RUNTERI
; Pulsbr. "abwärts" ;Lautsprecher ;Zyklusdauer ;noch nicht zu Ende ;Zyklu sdauer ;verringere Pulsbr. ; Zyklu s abge l au fen 5 Prozessortakte ; Zeitverzögerung ;ver ringere Pulsbr. ; Brei t e 0, "aufwärts" weitere 6 Prozessor t akte Zeitverz.
Sucht in der Tabelle die richtigen Werte von "AUF" und "AB" für die gegebene Note in "FARBE" mit dem gewünschten "KLANG". SUCHE
SHI FTEN
NULL
LDA ASL TAY LDA STA LDA LSR BEQ LSR BNE LDA SEC SBC STA
;gewünschte Note ;verdopple den Wert ;nutze ihn als Index TABELLE,Y ;s uche Tabellenwert AB ;s p. ihn a l s "AB" ;gewü nschter Klang KLANG ;passe "AB" an NULL ;durch "shiften" , ;bis ein Wert AB ;Null geworden ist SHIFTEN TABELLE , Y ;ho le Ursprungswert FARBE
AB AUF
;berechne Differenz ; s p. sie als "AUF"
4. Da steckt MUSIC drin 956A: 956B: 956E: 9570:
C8 B9 96 95 65 00 85 00
9572: 9574: 9575: 9578 : 957A : 957C : 957 E: 9580:
A9 38 ED 85 A9 85 A5 DO
9582: 9583: 9584: 9587: 9589 : 958B: 958D: 958F': 9590: 9591: 9594:
9596: 959E: 95A6: 95AE: 95B6: 95BE: 95C6: 95CE: 95D6: 95DE: 95E6 : 95EE : 95F'6:
EA EA 4C E6 DO E6 DO 60 EA 4C DO
00 CF' A4 82 67 52 41 33 29 20 lA 14 10
00 F'E 02 03 00 02 01 98
87 95 02 05 03 05 94 95 EC
00 CF' A4 82 68 52 41 34 29 21 lA 15 10
F'6 C3 9B 7B 61 4D 3D 30 26 lE 18 13 OF'
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 11 0 111 112 113 114 115 116 117 118 119 120 121 122 123
103 INY LDA TABELLE,Y ADC AB STA AB
;e rhöhe den Index ;ho le nächsten Wert ;addiere "AB" ;speichere Endwert
LDA SEC SBC STA LDA STA LDA BNE
;setze Akku auf Null ;b il de Komplement ;der gewünschten Dau er ;sp. a ls Hi-Byte ;setze das Lo-Bytex ; au f Null ; spielbare Note?? ;Ja , spie l e sie
11$00 DAUER LÄNGE+l 11$00 LÄNGE AUF' HOCH
Le ge für die Note 00 eine Pause ein von der se lb en Länge, a ls wenn s ie gespie lt würde PAUSE PAUSEl
PAUSE2 PAUSE3
NOP NOP JMP INC BNE INC BNE RTS NOP JMP BNE
;zur Zeitverzögerung ;7 Prozessortakte PAUSEl LÄNGE PAUSE2 LÄNGE+l PAUSE3 PAUSE3 PAUSE
;zähle Zyklusdauer
;Zyklu s i st zu Ende ;we it ere Prozessor;takte zur Zeitverz.
Tabelle mit den Notenwerten TABELLE
HEX 0000F'6F'6E8E8DBDB HEX CF'CF'C3C3B8B8AEAE HEX A4A49B9B92928A8A HEX 82827B7B74746D6E HEX 676861625C5C5757 HEX 52524D4E49494545 HEX 41413D3E3A3A3637 HEX 333430312E2E2B2C HEX 2929262724252223 HEX 20211E1F'lD1D1B1C HEX lA1A181917171516 HEX 1415131412121111 HEX 10100F'100EOF'
Damit Sie MUSIC auch gleich testen können , folgt ein kurzes DEMO-Programm : MUSIC .DEMO 5 PRINT CHR $ (4);"BLOAD MUSIC.OBJ " 10 MUSIC = 38167:KLANG = 765:DAUER = 766 F'ARBE 20 POKE DAUER,40 : POKE KLANG,32 30 F'OR I = 1 TO 49 40 POKE F'ARBE, I 50 CALL MUSIC 60 NEXT I : END
=
767
104
4. Da steckt MUSIC dr in
Für KLANG könne n sie die Werte 2, 4, 8, 16 , 32 und 64 wählen , wobei 32 der "No rm alfall " ist. FARBE reicht vo n 00 bis 50 , wobei 00 eine Pause darstellt. Statt FARBE können Sie auch NOTE sagen , aber nicht im BASIC-Programm benutzen , da Applesoft dara us NOT E macht. 32 entspricht ungefä hr de m C' . Die Erhöhung von FARBE um 1 erhö ht den Ton um eine n Ha lbton. Sie können so Melodien über 4 Oktaven programmieren. Das BASIC-Programm poked di e Werte für de n nächsten Ton in die Speicherste llen 765 bis 767 ($02FD - $02FF), von wo sie durch das Maschine nprogramm abgeho lt werden. Da die Parameterwerte nicht zerstört werden , müssen Sie nur die sich ändernde n Werte jedesmal neu poken. Da Tonleitern auf di e Dauer etwas ermüde nd sind , be reite n wir un s jetzt eine kleine Freude.
JOY 10 REM JOY FREI NACH BEETHOVEN 20 PRINT CHR$ (4) ; "BLOAD MUSIC.OBJ" 30 MUSIC = 38167:KLA NG = 765:DAUER = 766: FARBE = 767 40 RESTORE : POKE KLANG , 32 50 FOR I = 1 TO 63: READ N 60 POKE DAUER,30 * (1 + (N ) 300) + (N ) 200) + (N ) 100)) 70 POKE FARBE , N - ( 100 * ((N ) 300) + (N ) 200) + (N ) 100))) 80 CALL MUSIC: NEXT I 90 END 100 DATA 124,124,125,127,127,125,124 , 122,120, 120 110 DATA 122,124 , 224 , 22 , 222 , 00 , 124 , 124 , 125 , 127 , 127 120 DATA 125 , 124,122,120 , 120 , 122 , 124 , 222 , 20 , 220 , 00 130 DATA 322 , 124 , 120,122 , 24,25,124,120 140 DATA 122 , 24 , 25 , 124, 122,120, 122 , 315 , 124, 124 150 DATA 125,127 , 127 , 125 , 124 , 122,120,120 160 DATA 122 , 124 , 222,20,320 Die Noten sind in den DATA-Zeilen enth alten. Die beiden rechten Ziffern jeder Zahl geben de n Notenwert an. Die linke der drei Ziffern bestimmt die Tonlänge: ist sie nicht vorha nden , ergibt das eine viertel Note; ein e 1 bedingt eine halbe Note , eine 2 eine dreiviertel Note und eine 3 die ga nze Note . In de r Zei le 60 wird die Längen-Information umgesetzt . Die Zeile 70 reduziert den Wert N auf die letzten beiden Stelle n, da der zulässige· Bereich von 00 bis 50 reicht. We nn Sie möchte n , können Sie MUSIC auch vo n einem Asse mbler-Programm aus aufrufen . Das fo lgende Beispiel soll ein starte ndes UFO da rstell en . Die Tonfolge und die lange Laufzeit von ca. 65 Sekunde n wird e rzielt durch drei inein ander geschachtelte Sch leifen, bei denen ein e inne re Schleife die Startwerte der Sch leifenvari able aus der jeweils äuße ren Schl eife übernimmt.
4. Da steckt MUSIC drin
105
UFO
0803 : 0805 : 0808: 080A: 080D : 080F: 0811 : 08 13 : 0815 : 0817 : 0819 : 081C : 081 F: 0820: 0822: 0824 : 0826 : 0828: 082A: 082C: 082E: 0830: 0832: 0834: 0836:
A9 8D A9 8D A9 85 A9 85 85 A5 8D 20 38 A5 E5 85 BO E6 A5 85 C9 90 E6 10 60
01 FE 10 FD 01 PD 01 FE FF FF FF 17 FF FD FF EF FE FE FF 33 E5 PD DB
02 02
02 95
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
;*************************** U.F.O Start mit MUSIC * ;*************************** Laufzeit ca . 65 Sekunden ORG $803 SI S2 S3
Zähl sc hl ei fen EQU $PD EQU $FE EQU $FF Aufruf von "MUSIC OBJ" und Par ame t er $9517 $2 PD $2FE $2FF
MUS I C KLANG DAUER FARBE
EQU EQU EQU EQU
START
LDA U Ol STA DAUER LDA UI0 STA KLANG LDA U Ol STA SI LDA UO l STA S2 STA S3 LDA S3 STA FARBE JSR MUSIC SEC LDA S3 SBC SI STA S3 BCS LOOP3 INC S2 LDA S2 STA S3 CMP U3 3 BLT LOOP3 INC SI BPL LOOP2 RTS
LOOP LOOP2 LOOP3
;von $01 bi s $7F ;vo n $0 1 bi s $33
; Ton
Vo r dem Start von UFO muß von Ihn en "MUSIC.OBJ" in s RAM geladen werden. Ihrer Phantasie sind für weitere Musikstücke keine Grenzen gesetzt, solange Ihn en ein einstimmi ges Instru ment ausreicht.
106
5. Der mobile Punkt Im ersten Band haben wir uns schon ein wenig über Za hlenberechnungen unterh alten. Addition, Subtraktion, Mu ltipli kation und Division sin d Ihn en bekannt. Die betrachteten Zahlen hatte eine Gemeinsamkeit: es handelte sich immer um ganze Zahlen. Nu n könnte Ihnen aber der Sinn danach stehen, 1.345 mit 2.4 zu multiplizieren oder die Quadratwurze l aus 7 zu berechnen. In BASIC ist das keine größere Schwi erigkeit , in Assembler sind Sie aber einige Tage mit dem Programmi eren beschäfti gt, wenn Sie so lche Aufgaben nicht schon einmal vo rher gelöst haben. Was liegt da näher, als die ein geba uten Routinen des Applesoft auch in Asse mbler-Programm en mitzubenutzen und sich dadurch viel Arbeit zu ersparen. Wir müssen lern en, mit dem Fließko mm a-Paket des Applesoft-Interpreters umzuge hen. Da im englischen Sprachgebi et für das Komma ein Punkt gesetzt wird, heißen diese Routi nen dort "Floatin g-Po int Subroutines". Wie es zu diesem Namen kommt, werden wir jetzt sehen. Unser erster Schritt besteht darin , die Darste llung einer Zah l im internen Applesoft-Format zu verstehen. Da der Prozessor mit nichts anderem umge hen ka nn als mit Folgen von Nullen und Einse n, muß es ein en Weg geben, jede beliebi ge Zah l als Bitkette da rzustellen.
5.1 Mit Geschenkpapier und Schleife: Einpacken und Auspacken Ga nze Zah len werden zumeist III einem oder zwei Bytes dargestellt. Der Wertebereich geht dabei bis zu maximal 65535 ($FFFF). Wenn wir größere oder gebrochene Zahl en betrachten, benutze n wir dazu das Fli eßkomm a-Form at. Für den Anfä nger ist dieses zumeist etwas schwierig zu ve rstehen. Wir werd en es deshalb gemeinsa m an einem Beispiel erarbeiten, für das wir di e Zah l 123,828125 benutzen wollen (von jetzt an schreiben wir 123.828125).
5.1 Mit Geschenkpapi er und Schleife : E inpacke n und A uspacken
107
Den Vorkomm a-A nteil kö nnen wir leicht in eine Bin ärzahl um wa nde ln : 123 = 1*26 + h 25 + h2 4 + h 23 + 0*2 2 + h i + h2(J = 1111011 Hexadezimal erhalten wir den Wert $7B. Mit den Nachko mm a-Stellen müssen wir genauso ve rfahren, nur daß wir dies mal die negati ve n Zweierpotenzen berücksichtigen mü sse n: .828125 = h2" + h2-2 + 0*2- 3 + h2-4 + 0*2- 5 + h2-6 = .110101 Setze n wir beides zusammen, erh alten wir: 123.828125 = % 1111011.110101 Wenn wir den Dezim alpun kt um eine Stelle nach links schie ben, bede utet das eine D ivision der Zahl durch 2. Soll der Za hlenwert ko nstant we rden, müssen wir den neu erhaltenen We rt zu m A usgleich mit Potenzen vo n 2 multiplizieren. Die folgenden A usd rücke sin d alle gleichwe rtig: 2° * % 1111011 .110101 i * % 111101.1110101 22 * % 11110 .11110101 23 * % 1111.011110101 24 * % 111.10111 10101 25 * % 11 .11011110101 26 * % 1.111011110101 27 * % .1111011110101 Die letzte Form , die vo r de m D ezim alpunkt keine Stellen mehr aufweist , ist für uns beso nders wichtig. Sie wird als die .. normalisierte Fo rm" de r Zahl bezeichnet . A ll e Z ah lenumwa ndlunge n in das Fließ komm a-Form at laufen übe r die norm alisierte Form , bei der der Dezim alpunkt soweit ve rschobe n wird , bis sich die am weiteste n links befin dliche 1 auf der rechten Seite des Punktes befind et. Wegen der Ve rschie bung des Ko mm as (des Pun ktes) werden so lche Z ahlen "Fli eßkomm a-Zahlen" (Floating-Point-Numbers) genannt. Die Za hl 7 stell t den Exponenten und % .11110111 10101 die Mantisse der Zahl dar. Wenn wir wollen, kö nnen wir die Mantisse auch hexadezimal schreiben. Wir trennen dazu ab dem Punkt von lin ks nach rechts imme r 4 Bits ab un d rechnen sie zur H EX-Zah l um : 1111 = $F 0111 = $7 1010 = $A 1000 = $8 Das letzte un vo llständige Nibble füllen wir mit Null en auf. Wir bekommen damit 123. 828125 = 2 7 * % .1111011110101 = 2 7 * $ .F7A8
5. Der mobile Punkt
108
Applesoft benutzt zwe i mterne Darste llungsweisen für Fließkommazahlen. Betrachten wir zunächst die ungepackte Form , die immer 6 Bytes belegt. Ein Byte wird für den Exponenten benutzt, 4 Bytes für die Ma ntisse und 1 Byte für das Vorze ichen. Exp.
Mantisse
Vorz.
Beim Exponenten weist Applesoft noch eine Besonderheit auf: zu dem eige ntlichen Exponenten wird $80 addiert . Im Vorzeichen -Byte ist nur Bit 7 interessant: ist es gesetzt, ist di e Zahl negativ , ist es gelöscht , so ist die Zahl positiv aufzufassen. Dies entspri cht der uns bekannten Form einer vo rzeichenbehafteten Ganzzahl. Aus 123.828125 wi rd dam it Exp. 8 7
Mantisse F 7
A8
0 0
Vorz. 0 0
0 0
Die nicht benutzten Bytes der Mantisse werden mit Null en gefü llt. Für die negative Za hl -123.828125 erh alten wir Exp. 8 7
Mantisse F 7
A8
0 0
Vorz. 0 0
F 7
Obwohl nur Bit 7 des Vorzeichen-Bytes von Bedeutung ist , setzt App lesoft hier meist das erste Mantissen-Byte mit entsprechend gesetztem Bit 7 ein . Die ungepackte Form ei ner Fli eßkomm azahl wird von App lesoft für alle internen Berechnungen benutzt. Zum Abspeich ern ist die ungepackte Form jedoch recht platzverschwendend , da vom 6. Byte nur 1 Bit benötigt wird. Appl esoft benutzt dazu die gepackte Form, die led iglich 5 Bytes benöti gt. Die Umwand lung ist recht ei nfach: Durch die Normalisierung ist das erste Bit rechts vo m Dezimalpunkt eine 1. Da dies immer so ist (mit Ausnahme der Zahl Null ), hat dieses Bit keinen eigentlichen Informationsgehalt , auch wenn es für Berechnungen benötigt wird . In der gepackten Form wird deshalb das Vorzeichen bit in Bit 7 des ersten Mantissen-Bytes aufbewa hrt , d.h. es bleibt 1, wenn die Zahl negativ ist, es wird 0, wenn die Zahl positi v ist. Für Berechnungen wird da raus die ungepackte Form zurückgewonnen . (Jetzt können Sie sich auch erkl ären, warum bei negati ve n Zahlen das Vorzeichen-B yte in der ungepackte n Fo rm Teile des ersten Mantissen-Bytes enthält). Wandeln wir di e uns nun schon vertraute Zahl in die gepackte Fo rm um : F1ießkomma-Zah1
ungepackte Form
gepackte Form
123.828125 -123.828125
87 F7 A8 00 00 00 87 F7 A8 00 00 F7
87 77 A8 00 00 87 F7 A8 00 00
=
5. 1 Mit Geschenkpapier und Schleife: Einpacken und Auspacken
109
Die Za hl Null paßt nicht in unser System, da sie nicht so normalisiert werden kann, daß rechts vo m Punkt ei ne 1 steht. App lesoft ben utzt für Null deshalb den Wert 00 00 00 00 00. Ge nauge nomm en wird jede Fließkom madarstellung, die im Expo nenten den Wert $00 enthält, vo n Applesoft als Null angesehen. Ein weiteres Prob lem ist noch nicht gelöst: wie werden Za hlen dargestell t, deren Betrag zw ischen 0 und 1 liegt . Betrachten wir 0.5. In der Exponenti alschreibweise erha lten wir 0.5 = 2- 1 = 2° * % .1 Dieser Wert ist bereits normalisiert, so daß wir ihn leicht in die ungepackte Form umwandeln können : 0.5 = 808000000000 (ungepackt) Da 0.5 positiv ist, muß für die gepack te Fo rm das Bit 7 des zwe iten Bytes (I. Ma ntissen- Byte) gelöscht werden . Wir erhalten damit 0.5 = 8000000000 (gepackt). Mit dem negative n Wert ist es dann ga nz einfach: -0.5 = 808000000080 (ungepackt) -0.5 = 8080000000 (gepackt). Kommen wir zu einem zweiten Beispiel: 0.25 . 0.25 = 2-2 = 2° * .01 U m diesen Wert zu norma lisieren, müssen wir den Dezimalpunkt nach rechts versch ieben. Zum Ausgleiche schreiben wir eine Zwe ierpotenz mit negativem Exponenten davor: 2° * .01 = 2- 1 *.1 Um zum Exponenten der ungepackten Form zu gelangen, müssen wir $80 zu dem so gefundenen Exponenten add ieren : -1 + $80 = $7F. Wir erhalten damit .25 = 7F 80 00 00 00 00 (ungepackt) .25 = 7F 00 00 00 00 (gepackt) Wenden wir uns einem letzten Beispiel zu . .375 = 2- 2 + 2- 3 = 2- 1 * .11 .375 = 7F CO 00 00 00 00 (ungepackt) .375 = 7F 40 00 00 00 (gepackt) - .375 = 7F CO 00 00 00 CO (un gepackt) - .375 = 7F CO 00 00 00 (gepackt). Zu m Abschluß wo llen wir noch die Frage beantworten , wie groß die größte positive Zahl ist , die Applesoft darste llt. Es ist FF 7F FF FF FF = 1.70141183E+38
5. Der mobile Pun kt
110
5.2 Alles ist fließend Auf der Zero-Page si nd für Applesoft zwei Speicherbereiche für ungepackte Fließkomm a-Zahlen vo rgesehen. Der Haupt-Fließkomma-Akkumulator (Main Floating-Point Accumul ator, MFAC oder FAC abgekürzt) reicht von $009D bis $00A2. Der sekun däre Fli eßkomm a-Akkumul ator (Secondary Floating-Point Accumulator, SFAC ode r ARG genann t) belegt di e Speicherplätze von $00A5 bis $OOAA .
MFAC
Exp. $009D
Manti sse $009E - Al
Vorz. $00A2
Ma ntisse $00A6 - A9
Vorz. $OOAA
SFAC
Exp. $00A5
Daneben gibt es noch 2 H ilfs-Fließko mm a-Akkumulatoren, die aber nur gelegentlich benötigt werde n. Die Bezeichnung "Akk umulator" wurde hier gewä hlt , da all e Fließkomma-Routinen mit diesen Speicherstellen rechn en, so daß sie für die Berechnun gen eine ähnliche Bedeutung besitzen wie der Akkumul ator des Prozesso rs für die einfachen Rechenoperationen des Prozessors. Der Fl ieß komma-Akkumulator hat aber nichts mit dem Prozesso r-A kkumul ator zu tun . Im ROM des Apple sind einige Fli eßkomm a-Zahlen verborgen, die de r Applesoft-Interpreter für sein e eigenen Berechnungen be nötigt. Wir können sie mitbenutze n, wenn wir ihre Lage kennen. Darunter sind so nützliche Ko nstanten wie die Kreiszahl Pi oder der natürliche Loga rithmus von 2.
5.2 Alles ist fließend
111
Fließkomma-Zahlen im ROM Wert
Startadresse
Inha lt
00 -32768.0005 1 0.434255942 0.576584541 0.961800759 2.885390074
$E09A $EOFE $E913 $E919 $E91E $E923 $E928 $E92D $E932 $E937 $E93C $EA46 $EA50 $EDOA $EDOF $EDI4 $EE64 $EEDB $EEEI $EEE6 $EEEB $EEFO $EEF5 $EEFA $EEFF $EF04 $EFA6 $EFAA $F066 $F06B $F070 $F076 $F07B $F080 $F085 $F08A $F08F
0000 (nur Exp ./ 1. Mantisse) 9080000020 8100000000 7F 5E 56 CB 79 8013 9B OB 64 8076389316 8238 AA 3B 20 803504 F3 34 813504 F3 34 8080000000 8031 72 17 F8 86 AB 20 CE E7 8420000000 9B 3E BC IF FD 9E 6E 6B 27 FD 9E 6E 6B 28 00 8000000000 8138 AA 3B 29 (l/In 2) 713458 3E 56 7416 7E B3 IB 77 2F EE E3 85 7A 10 841C 2A 7C 63 59 58 OA 7E 75 FD E7 C6 8031 72 18 10 8100000000 983544 7A 68 6828 BI 4620 8149 OF DA A2 8349 OF DA A2 7F 00 00 00 00 84 E61A 20 IB 862807 FB F8 8799688901 872335 DF EI 86 A5 50 E7 28 8349 OF DA A2
\/V2 \/2 -0.5 In 2 -42.78203928 10 99999999 .906 999999999.25 109 0.5 1.442695041 2.14987636*10. 5 1.4352314*10.4 1. 34226348* 10-3 9.6140170hl0-3 5.55051269* 10- 2 0.2402263846 0.6931471862 1 1.18795464*107 3.92767778*10- 8 rr/2 2*rr 0.25 -14.3813907 42.0077971 - 76.7041703 81.6052237 -41.3417021 2*rr
112 -6.84793912*10-4 4.85094216*10. 3 -1. 61 117018*10. 2 3.42096380*10. 2 - 5 .42791328* 10.2 7.24571965* 10"2 -8.98023954* 10.2 0.110932413 -0.142839808 0.19999912 -0.333333157 1 0.811635157
5. Der mobile Punkt $FOCF $FOD4 $FOD9 $FODE $FOE3 $FOE8 $FOED $FOF2 $FOF7 $FOFC $F101 $FI06 $Fl 23
76 B3 83 BD D3 791E F4 A6 F5 7B 83 FC BO 10 7C OC 1F 67 CA 7C OE 53 CB C l 7D 1464 70 4C 7DB7EA517A 7D 63 30 88 7E 7E 92 44 99 3A 7E 4C CC 91 C7 7F AA AA AA 13 8100000000 80 4F C7 52 58
Die allermeisten dieser Zahl e n we rden Sie nicht benötigen , da es sich dabei um Reihenkoeffizienten für die inte rne n Umrechnungen des Interpreters ha ndelt. Sie sind aber de r Vollständigkeit halber a ufgeführt , damit Sie nicht zu lange knobeln müssen , we nn Sie sich einm al daran machen , A pplesoft zu disasse mbli e ren.
5.3 Das Zauberpaket wird entschnürt Um Fließkomma-Zahlen im Speicher hin- und herzu bewegen sowie zum Packen/ E ntpacken stehen zahlreiche ROM-Ro utinen zur Verfügung. Wir wollen die Möglichkeite n hier nur streife n und auf große Programme ve rzichten , da Mathematik-Programme zumeist se hr indi viduell geschrieben werden müssen . Zunächst erpro ben wir ein einfaches Multiplikations-Programm: 0.25 * 10 . Wir benutzen dazu die gepackten Fli eßkomm aza hlen aus dem ROM und die Multiplikationsroutine FMULIT ($E982) . FMULIT multipliziert den MFAC mit dem SFAC und legt das E rgebnis im MFAC ab. Dazu müsse n wir unse re Zahlen e ntpacken und in die Fließkomma-Akkumulatoren schaffe n. MOVFM ($EAF9) übe rträgt die angegebene Zahl aus dem Speicher (Memory) in den MFAC. Zusätzlich zum MFAC wird noch ein 5. Mantissen-Byte bei $OOAC angelegt , das die Rechengenauigkeit e rhöh en soll. Der Aufruf von FMULT ($E97F) übe rträgt di e a ngegebene Zahl in den SFAC und ruft dann die eigentliche Multiplikationsroutine FMULIT ($E982) auf. Um die Lage einer gepack ten Zahl im Speicher anzugeben, müssen wir den Akk umul ato r (des
5.3 Das Zauberpaket wird entschnürt
113
Prozessors!) mit dem Lo-Byte und das Y-Register mit dem Hi -Byte ihrer Adresse laden , bevor wir die ROM-Routine aufrufen. Eine Kleinigkeit ist noch zu beachten. Die Speicherstelle $OOAB muß den Wert des Exclusive-OR verknüpften Vorzeichenbytes von MFAC und SFAC enthalten. Sowohl MOVFM als auch FMULT erledigen dies für uns mit.
FP-DEMO
0300 : 0301 : 0304: 0306: 0309: 030C: 030E: 0311 : 0312: 0314: 0316 : 0319: 031B: 031D: 0320: 0323: 0326: 0328: 032B: 032E : 0330: 0333 0334 0336
D8 20 AO B9 20 A9 20 C8 CO 90 20 A9 AO 20 20 20 AO B9 20 A9 20 C8 CO 90
58 00 50 DA AO ED 05 FO 8E 50 EA F9 70 8E 00 70 DA AO ED 05 FO
FC EA FD FD
FD EA 03 FD FO FD FD
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
;********************* FP - Demonstration * ;********************* DOSWRM ZEHN VIERTEL
EQU $03DO EQU $EA50 EQU $F070
MFAC FMULT MOVFM MOVMF SIN
EQU EQU EQU EQU EQU
$009D $E97F $EAF9 $EB2B $EFFl
HOME CROUT PRBYTE COUT
EQU EQU EQU EQU
$FC58 $FD8E $FDDA $FDED
ORG $0300 START LOOPI
LOOP2
CLD JSR LDY LDA JSR LDA JSR INY CPY BLT JSR LDA LDY JSR JSR JSR LDY LDA JSR LDA JSR INY CPY BLT
;Binärmodus HOME UOO ZEHN,Y PRBYTE #" " COUT
;ausgeben ; HEX-Zahl ;Leerzeichen
U05 LOOPI ; CROUT #< ZEHN #> ZEHN MOVFM Mem -> MFAC SHOWM anzeige n CROUT UOO VIERTEL , Y ausgeben PRBYTE HEX-Zah l #" " Le erze ichen COUT U05 LOOP2
114 0338: 033B: 033 E: 0340: 0342: 0345: 0348: 034B: 034D: 034F' : 0352: 0355: 0358: 035B: 035 E: 0360: 0362: 0365: 0368:
5. De r mobil e Punkt
20 20 A9 AO 20 20 20 A2 AO 20 20 20 20 20 A2 AO 20 20 4C
0370: 0372: 0375: 0378: 037A: 037D: 037E: 0380: 0382:
AO B9 20 A9 20 C8 CO 90 4C
0385: 0387: 038A: 038D: 038F': 0392 : 0393: 0395 : 0397 :
AO B9 20 A9 20 C8 CO 90 4C
8E 8E 70 F'O 7F' 8E 70 6B 03 2B 85 8E F'1 70 6B 03 2B 85 DO
PD F'D E9 PD 03 EB 03 F'D EF' 03 EB 03 03
00 9D 00 DA F'D AO ED PD 06 F'O 8E F'D 00 6B 03 DA PD AO ED F'D 05 F'O 8E F'D
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
JSR JSR LDA LDY JSR JSR J SR LDX LDY J SR J SR JSR JSR JSR LDX LDY JSR JSR JMP
CROUT CROUT # V IERTEL F'MULT CROUT SHOWM #<SPEICHER #>S PEICHER MOVMF' SHOWSP CROUT SIN SHOWM #<SP EICHER #>S PEICHER MOVMF' SHOWSP DOSWRM
;
;Mem -> SF'AC , dann ; mul tiplizieren ;anzeigen ; MF'AC - > Mem ;Spei cher a nzei gen ;S i nus berechnen ;MF'AC zeigen ;MF'AC - > Speicher ; Wa r ms tart über DOS
SPEICHER
DF'S 5
;Spe i cherplatz
SHOWM LOOP3
LDY LDA JSR LDA JSR INY CPY BLT JMP
;MF'AC anzei ge n
SHO WS P LOOP4
LDY LDA J SR LDA J SR INY CPY BLT JMP
#$00 MF'AC , Y PRBYTE :#= 11
11
COUT #$06 LO OP3 CROUT #$0 0 ;Speicher anze i gen SPEICHER,Y ;anze i gen PRBYTE ;HEX-Zahl =#= 11 ; Leerze i chen COUT 11
#$05 LOOP4 CROUT
; , dann zurück
Das Programm benutzt zwe i Monitor-Routinen , di e wir bisher noch nicht behandelt ha ben. CROUT ($FD8E) gibt ein " Caniage Return " ($8D) über COUT aus. PRBYTE ($FDDA) gibt das Byte im A kkumul ato r über COUTals 2-ziffrige HEX-Zahl aus.
5.3 Das Zauberpaket wi rd entschnürt
115
CROUT $FD8E Gibt $8D über COUT aus. E ingabe: Ausgabe : Akku = $8D
PRBYTE $FDDA G ibt Akk umul ator als ASCII-HEX-Zahl über COUT aus Eingabe: Akk u = HEX-Zahl Ausgabe: Akku zerstört!
Nach dem Löschen des Bildschirms sehen Sie in der e rsten Zeile die gepackte Zahl 10 , darunter die ungepackte Zah l, so wie sie im MFAC steht. Es fo lgt die gepackte Zahl 1/4. Das Endergebnis der Multipli kation (2.5) steht wiederum ungepack t im MFAC und wird darunter ausgegeben . Sch li eßlich wird das Ergeb nis noch in den Speicher kop iert und dabei erneut gepackt (MOVMF $EB2B). 84 20 00 00 00 84 AO 00 00 00 20
10 gepac kt 10 ungepackt
7F' 00 00 00 00
1/4 gepackt
82 AO 00 00 00 20 82 20 00 00 00
2.5 ungepackt 2.5 gepackt
80 99 35 78 6E 18 80 19 35 78 6E
SIN 2.5 ungepackt SIN 2.5 gepackt
Applesoft bietet einen ga nze n Satz von Funktionen an, a us dem wir ste llvertretend die Sinus-Funkt ion benutzen. A lle Funktionen wirken auf den MFAC und werden genau wie SIN ($EFF1) aufgerufe n. Das Rechen e rgebn is fi ndet sich wiede r im MFAC. Auch den Si nus von 2.5 sehen wir uns ungepackt und dann im SPEICHER gepackt an. D a bei kö nnen Sie festste llen, daß die ungepackte Form im Vorzeichenbyte gelegentli ch auch abweichende Werte aus Zwische nergebnissen e nthalten kann. Vo n Bede utung ist nur Bit 7.
116
5. Der mobile Punkt
FP-Operationen mit einem Operanden Alle folgenden Routinen beziehen sich auf den MFAC , der vorher entspreche nd gelade n werden muß .
NOT
FALSE TRUE FADDH NORM ZEROFAC LOG MULTlO
DIVIO RNDB SGNA
SGN
ABS INT SQR NEGOP EXP RND
COS SIN TAN ATN
$DE98 negiert MFAC MFAC = 00 => MFAC = 1 MFAC =F 00 => MFAC = 0 $DF5D trägt 0 im MFAC ein (nur $009D!) $DF60 trägt 1 im MFAC ein $E7AO addiert 0.5 zum MFAC $E82E norm ali siert MFAC mit 5. Mantissen-Byte $E84E setzt MFAC auf Null ($009D und $00A2) $E941 natürlicher Logarithmus vom MFAC $EA39 multiplizie rt MF AC mit 10 $EA55 dividiert MFAC durch 10 $EB72 das 5. Mantissen-Byte wird nach MF AC gerunde t $EB82 Vorzeiche n vo n MFAC testen. MFAC< 0 => Ak ku = $FF MFAC = 0 => Akku = $00 MFAC > 0 => A kku = $01 $EB90 trägt das Vo rzeichen vo m MFAC im MFAC ein (der alte Inh alt wird zerstö rt!) MFAC< 0 => MFAC = -1 MFAC = 0 => MFAC = 0 MFAC> 0 => MFAC = 1 $EBAF bildet den Betrag vo m MF AC $EC23 iso liert de n ganzzahligen A nteil $EE8D be rechnet die Quadratwurzel vo m MFAC $EEDO bi ldet den negativen Wert vom MFAC $EF09 ex poni ert MFAC zur Basis e (2.718 .. .) $EFAE berechnet eine "Zufallszahl " in Abhängigkeit vo n MFAC. In $00C9-CD muß vorher ein Startwert stehen. MFAC und $00C9-CD enthalten ne ue Zufallszahl. $EFEA be rechnet Cosinus vom MF AC $EFFl berechn et Sinus vom MF AC $F03A berechnet Tangens vom MFAC $F09E berechnet A rcustangens vo m MFAC
5.3 Das Zauberpaket wird entschnürt
117
Die fo lgenden Routinen benötigen 2 Operanden, von denen ei ner im MFAC und der andere im SFAC stehen muß. Mit Ausnahme der Potenzfunktion haben all e Routinen zwei E intrittspunkte: der erste nimm t an, daß MFAC schon ge laden ist , und überträgt vor der eigentli chen Operation die gepackte Fließkomma-Zahl , auf die de r Akk umul ato r und das Y-Register (Lo/Hi) zeigen , nach SFAC. Der zweite E intrittspunkt erwartet , daß MFAC und SFAC gelade n si nd , und führt sofort die Opera ti on aus. Vor dem A ufruf muß der Exponent von MF AC in den Akku mul ator geladen werden (LDA $9D)!! Das Ergebnis findet sich immer im MFAC.
FP·Operationen mit zwei Operanden FSUB FSUBT FADD FADDT FMULT FMULTT FDIV FDIVT FPWRT
$E7A7 überträgt ge packte Zahl (A ,Y) nac h SFAC und führt dann FSUBT aus $E7AA subtrahiert MFAC von SFAC (SFAC - MFAC) $E7BE überträgt gepackte Zahl (A,Y) nac h SFAC und führt dann FADDT aus $E7C1 add iert SFAC und MFAC (SFAC + MFAC) $E97F überträgt gepackte Zahl (A,Y) nach SFAC und führt dann FMULTT aus $E982 multipliziert SFAC und MFAC (SFAC * MFAC) $EA66 überträgt gepackte Zahl (A ,Y) nach SFAC und führt dann FDIVT aus $EA69 dividiert SFAC durch MFAC (SFAC/MFAC) $EE97 potenziert SFAC mit MFAC (SFAC i MFAC)
Es folgen noch eini ge weitere Routinen, die nicht in ein Schema passen.
Logische Operationen und Vergleiche NOT
OR
AND
$DE98 negiert MFAC MFAC = 00 => MFAC = 1 MFAC =1= 00 => MFAC = 0 $DF4F verknüpft SFAC und MF AC durch logisch es ODER. Ist ein Operand =1= 0, wird MFAC = 1, sonst ist MFAC = O. $DF55 verknü pft SFAC und MFAC durch logisches UND . Sind beide Opera nden =1= 0, wird MFAC = 1, so nst ist MFAC = 0
5. Der mobil e Punkt
118 COMP
$0016 1
2 3 4 5 6 FCOMP
$DF6A vergleicht SFAC mit MFAC. MFAC wird auf 1 gesetzt , wenn der Vergleich wahr ist, andernfa lls auf O. Di e Speicherstelle $0016 bestimmt den Typ des Vergleichs: Vergleich SFAC> MFAC SFAC = MFAC < = > SFAC ~ MFAC 42 1 SFAC< MFAC SFAC MFAC SFAC~ MFAC $EBB2 subtrahiert den MFAC vo n der gepackten Zahl , auf die der Akkumulator und das Y-Register (Lo/Hi) weisen. Setzt den Akk umul ator entsprechend dem Ergebnis. Zusätzlich wird die Nullflagge im Statusregister gesetzt, wenn beide Zahl en übereinstimmen. MFAC< Zahl => Ak ku = $FF MF AC = Zahl => Akku = $00 MFAC > Zahl => Akku = $01
*
5.4 Sich regen bringt Segen Alle bisherigen Ro uti nen gingen davon aus, daß sich di e Fli eßkomm a-Zahlen schon irgendwo im Speicher befinden. In einem Programm ist das zumeist aber nicht der Fall. Wir benötigen also weitere Möglichkeiten, um Zahl en inn erhalb des Speichers zu bewegen und um Zahl en zwischen der Fließ komma-Darstellung und anderen Betrachtungswe isen zu wandeln , de nn schließli ch sind in 5 Bytes gepackte Zahlen nicht sehr anschauli ch. Die fo lgenden Routi nen dienen dem Verschieben von Fli eßko mma-Zahlen un d der Umwandlung zwischen ge pack ter und ungepackter Fo rm . Der Akk umulator und das Y-Register ze igen gege benenfalls auf das Lo- bzw. das Hi-Byte der Anfa ngsad resse (Exponentenadresse). FP-Übertragungs-Routinen MOVESM
$E9E3 überträgt gepackte Zahl (A ,Y) nach SFAC. Die Vo rzeichen vo n MFAC und SFAC werden verknüpft und nach $OOAB gespeichert.
5.4 Sich rege n bringt Segen
MOVEFM MOVE2F MOVEIF MOVEZF MOVEMF MOVEFS MOVESF
119
$EAF9 überträgt gepackte Za hl (A ,Y) nach MFAC, legt ein auf Null gesetztes 5. Mantissen-Byte an $EBIE überträgt MFAC in den 2. H il fsfließkomma-Akkumul ator ($0098-9C) $EB21 überträgt MFAC in den 1. Hilfsfl ießkomma- Akkumulator ($0093-97) $EB23 überträgt MFAC in die Zero-Page Speicherstelle , auf die das X-Register weist $EB2B rundet MFAC und überträgt ihn als gepack te Zahl nach (X,Y)!!! $EB53 überträgt SFAC nach MFAC $EB63 überträgt MFAC nach SFAC
Die beiden wichtigsten Formen der Zahl endarsteIlung im Apple sind das Fließkomma-Format und das vorze ichen behaftete Ganzza hl- Fo rm at (signed Integer). Eine letzte Klasse von Routinen des Applesoft-Inte rpreters dient nun zur Umrechnung (Ko nvertierung) zwischen diesen beiden Syste men. E in Programm beispiel fo lgt in Kapitel 7.
FP -Konvertierungs-Routinen VARL
VARLl
MKINT
AYINT
GIVAYF
$DED5 überträgt den Wert ein er Vari ab len nach MFAC , wenn es sich um eine num erische Va ri able handelt. TXTPTR ($00B8/B9) muß auf das erste Zeichen des Variablenn amens zeigen. $DEE9 VPNT ($OOAO/A l ) enth ält die Sta rtad resse der 2-Byte-Integerzahl mit Vorzeichen, die nach MFAC übertragen wird. $EI08 verwandelt den MFAC in eine 2-Byte-Integerzahl in VPNT ($OOAO = Hi/$OOAl = Lo!!). MFAC muß positiv und < 32768 sein, so nst erfo lgt Fehlermeldung. $ElOC verwandelt den MFAC in eine 2-Byte-Integerza hl mit Vorzeichen in VPNT ($OOAO/Al = Hi/Lo!). MFAC muß zwischen -32768 und +32768 liegen, sonst erfolgt Fehlermeldung. $E2F2 verwandelt eine vo rzeichen behaftete 2-B yte-ln tegerzahl (Y-Reg = Lo, Akku = Hi) in ein e Fließkomma-Zahl in MFAC
120
SGNFLT
CONINT
GETADR
FLOAT QUINT
FIN
PRNTFAC FOUT
5. Der mobile Punkt $E301 die 1-Byte-Integerzahl ohn e(!) Vorzeichen im Y-Register wird in eine Fließkommazahl in MFAC umgewandelt. Der Akk umulato r muß beim Aufruf Null se in (Akku = 00). $E6FB verwandelt den MFAC in eine 1-Byte-Integerzahl im X-Register. Routine endet nicht mit RTS sondern mit JMP CHRGOT ! $E752 verwandelt den MFAC in eine 2-Byte-Integerzahl ohne Vorzeichen in LINNUM ($0050 = Lo, $0051 = Hi). Wertebereich 0 - 65535. $EB93 verwandelt die vorzeiche nbe haftete 1-Byte-Integerzahl im Akkumulator in eine Fließkomma-Zahl im MFAC. $EBF2 verwa ndelt MFAC in eine 4-Byte-Integerzahl mit Vorzeichen. Ergebnis wird von $009E bis $00A2 mit dem Vorzeichen in Bit 7 von $009E abgelegt. $EC4A verwandelt einen String in ein e Fließkommazahl. TXTPTR muß vor das e rste Zeichen zeigen. Zuerst "JSR CHRGET" ausführen , dann "JSR FIN". String muß mit gelöschtem Bit 7 im Speicher stehen und mi t ,,:", $00 oder Nichtzahl-Zeichen enden. $ED2E gibt den MFAC als Dezimalzahl über COUT aus. Benutzt FOUT , STROUT und COUT. $ED34 verwandelt den MFAC in einen Zahlenstring ab $0100 um (im Stack). String hat Bit 7 gelöscht und $00 als E ndm arke r. Akku (Lo) und Y -Register (Hi) zeigen auf den Stringanfang.
Wenn Sie in ei nem Programm kurzfristig den MFAC retten müsse n , können Sie die Routine PSHMFAC ($DElO) benutzen , um die Fließkomma-Zahl auf den Stack zu retten. Mit PULLSFAC ($DE47) kann sie von dort zurück in den SFAC geholt werden. Da beide Routinen den Stackpointer versetzen, können sie nicht einfach mit JSR aufgerufen werden. PSHMFAC zieht die ReturnAdresse vom Stack und legt sie (nach Addition von 1) in den Speicherstellen $005E und $005F ab. Die Routine endet mit einem JMP ($5E). PULLSFAC endet mit einem RTS . Da vorher aber bereits die Fließkomma-Werte vom Stack geholt werden, muß vor der Fließkomma-Zahl bereits die Rücksprungadresse auf dem Stack liege n und PULLSFAC mit ei nem JMP aufgerufen werden.
PSHMFAC
$DE10 sch iebt MFAC von hinten mit dem Vorzeichen beginnend auf den Stack. Holt sich vorher seine Rücksprungadresse vom Stack und springt sie späte r mit JMP 0 an.
5.4 Sich regen bringt Segen
PULLSFAC
121
$DE47 holt 6 Bytes vom Stack und legt sie im SFAC ab. Routine muß mit JMP aufgerufen werden (nicht JSR) und erwartet die Rücksprungadresse oberhalb der Zahl auf dem Stack.
Ein kurzes Beispiel so ll die Lage durchsichtig machen: LDA #<WEITER PHA LDA #) WEI TER PHA JSR PSHMF'AC JMP PULLSF'AC WEITER
;Returnadre sse für PULLSF'AC ; MF'AC - ) STACK ; Ih re Routinen ;STACK - ) SF'AC ;hierhin kehrt PULLSF'AC zurück
Ihre eigene n zwischengeschalteten Routinen müssen zwa ngsläufig den Stackpointer unverändert lasse n, d.h. er darf zwischenzeitlich verä ndert werden, wenn er vor dem Aufruf von PULLSFAC wieder auf seinen alten Wert zurückgebracht wird. Unser Fließkomma-Paket ist entschnürt. Aus Platzgründen können nicht für alle Routinen Anwendungen angegeben werden. Die verschiedenen Tabell en sind aber ausreichend , um ga nze Mathematik-Programme mit reell en Zahl en in Assembl er zu schreiben. Sie können alle Unterprogramme benutzen, auch wenn Sie nicht wissen, wie der Applesoft-Interpreter in tern z.B. einen Logarithmus-Wert berechn et. Auch im nächsten Kapitel über Appl esoft-Variablen werden wir einen Teil der Fli eßkom ma-Ro utin en sinnvo ll für uns nutze n.
122
6. Und immer schön variabel bleiben! Appl esoft hat eine weitere Eigenschaft, di e wir als Asse mbler-Programmi erer mitbenutzen kö nnen: di e Vari abl en. Wenn wir Programm e schreiben wollen, die sowohl aus BASIC als auch aus Teil en in Maschin ensprache bestehen, ist eine Ke nntnis über den Aufbau und di e Verwaltung der Applesoft- Va ri ablen unumgängli ch. Nur wenn wir auch von der Maschin ensp rache auf Vari abl en zugreife n kö nnen , ist es ein fach möglich, zwischen BASIC und Assembler Inform ationen auszu tauschen. Alles andere führt zu ein em zeit- und pl atzverschwendenden "herumpoken" .
6.1 Eine Tabelle ist aller Variablen Anfang Applesoft un terscheidet 3 Typen von einfac hen Va riablen, 3 Typen von Feldvari ablen und einen Fun kti onstyp. Sie werden in BASIC durch die Schrei bweise unterschieden: Reell e Zahl : nu r Na me z.B. A Ganzzahl : Na me mit angehängtem ,,% " z.B. A% Name mi t angehängtem ,,$" z.B. A$ Ze ichenkette : Fun ktion: Name mi t vorangestell tem "FN" z.B. FN A(B) Feld : Name wie oben, mit angehängtem In dex z.B. A(l), A %(1), A$ (l) Betrachte n wir zunächst di e einfac hen Va ri ablen. Applesoft legt alle ei nfac hen Vari abl en in einer Tabelle ab, die dem BASICProgramm normalerweise unmittelbar fo lgt. Auf der Null-Se ite ist der Ze iger VARTAB ($0069/6A) vorh anden, der imm er auf den Beginn der Tabelle ze igt. Dieser Wert ist mit dem BASIC-LOMEM: identi sch . Die Adresse des ersten
6.1 Eine Tabelle ist aller Variablen A nfang
123
Bytes hinter der Tabelle ist in ARYTAB ($006B/6C) abgelegt. Jeder E intrag in der Tabelle ist 7 Bytes lang , auch wenn nicht immer alle 7 Bytes benötigt werden.
DOS
HlM EM 1$73174)
normal $9600 Sir ingpool
fRETOP 1$6f!70)
frei STREHD 1$60/6E)
+ +
feldvariablen ARVTAB 1$6B/6C)
einfache Variablen VARTAB 1$69/6A)
LOMEM Applesoft- Programm normal ~ 0801
TXTTAB 1$67/6B)
Bildschirm
Abb . 8: Zeiger der Speicherbelegung
Die Auftei lung innerhalb der Tabell e geschi eht durch den Zeitpunkt der Variablendefinition. Die zuerst definierte Variable steht a n der untersten Position. Ihr folgt die a ls zweites definierte Variable usw. So kommt es , daß a lle Ty pen durcheinanderstehen. Die Funktionen finden sich ebe nfa ll s in der se iben Tabell e. Applesoft braucht also e in Unterscheidungsmerkmal, um die 4 Möglichkeiten ausein a nder zu ha lte n. Da sich Applesoft nur die ersten 2 Buchstaben vo n jeder Variablenbezeichnung merkt (HANS und HAUS bezeichnen für Applesoft also d ie gleiche Variable!), eigne n sich die bei den Bit 7 von jedem Namen sehr gut zu
124
6. U nd imm e r schön variabel bleiben!
diesem Zweck. E in gesetztes Bit 7 e rgibt eine n negativen Wert , ein ge löschtes Bit 7 ein en positive n We rt. Wir erhalten dami t: Variable n typ ree lle Zahl ganze Zahl Z eiche n kette Funkti o n
1. Zeiche n positiv 0 negativ 1 positiv 0 negati v 1
2. Zeiche n positiv 0 negati v 1 negati v 1 positiv 0
Die e rste n beide n Bytes jedes Tabelleneintrags enthalte n imme r die erste n beide n Bytes des Variable nn ame ns mit e ntsprechend gesetzten ode r ge löschte n Bits 7 . Ist die Variablenbezeichnung nur ein Zeichen lang, wird mit $00 bzw . $80 aufgefüllt. A => $41 $00 A % => $C1 $80 A$ => $41 $80 FN A(X) => $C1 $00 Die restlichen 5 Bytes habe n je nach Va riablentyp einen unterschiedlichen Inhalt. Bei den reellen Va riablen enthalten sie die gepackte Flie ßkomm aza hl. Die ganzen Zahlen belegen nur die e rsten beiden der 5 Bytes , die restlichen 3 sind mit $00 aufgefüllt. Die Z eichenketten passen nicht selber in die Tabelle , da ihre Länge bis zu 255 Z eiche n betragen kann . A pplesoft legt sie in de r R eihe nfo lge Ihres A uftrete ns bei H IMEM ($0073/74) beginnend abwärts ab (auf einige A usnahme n komme n wir späte r zu sprechen). Die Z eichenkette n stehen dabei in sich abe r wi eder aufwä rts. D as erste Byte der T abelle e nthält eine Längenangabe , das zweite und dritte Byte in der Ta belle zeigt auf das erste Byte de r Zeichenkette . Di e beide n letzte n Bytes sind leer ($00). We nn H IMEM bei $9600 li egt und " A BCDE" die erste definie rte Z eiche n kette ist , finden wir: $9600 = ??? ? <= HIMEM $95FF = E $95FE = D $95FD = C $95FC = B $95FB = A (- hie rhin zeigt der Tabelleneintrag D as unte re E nde des Zeichenkettenbereichs (Stringpool) wird in de m Zeiger FRETOP ($006F/70) fes tgehalten , da hi er der nächste auftrete nde String abgelegt we rden muß .
6.1 Eine Tabelle ist all er Variablen A nfa ng
125
D ie Tabell en wachsen also vo n unten (LOMEM:) nach oben, der Stringpool von oben (HIMEM :) nach unte n. T reffen beide Bereiche aufe in ander (STREND und FRETOP überkreuzen sich), ist der gesamte Speicher vo ll und A pplesoft gibt eine "MEMOR Y FULL E RROR" aus, we nn sich du rch ein e U morganisation des Speichers (Garbage Co ll ection = interne M üllabfuhr) ni cht noch wieder Platz gewinnen läßt. Bei den Funk tionen schließlich ist die Sache noch etwas ko mplizierte r. Nach den beiden Namensbytes finden wir hier nämlich in 2 Bytes einen Zeiger auf die Adresse der Speicherstelle nach de m ,, = "-Zeichen im BASIC-P rogramm . D ie Funktion sdefinition wird von A ppleso ft näml ich bei jeder Benutzung aus dem BASIC-Text gelesen. D ie nächsten beide n Bytes enth alte n die Adresse des Wertes der Pseudovaria blen, die bei der Definition in Klammern angegeben we rden muß. Sie zeigen also auf eine 5-Byte-G ru ppe innerhalb der seiben Tabelle . D as letzte Byt e enth ält schließlich das erste Zeichen nach dem ,,="-Zeichen im BASIC-Text , ev. in to kenisierter Fo rm . Di esesByte wird aber an kein er Stell e ausgewertet. Fassen wir unse re E rkenn tn isse noch einmal in einer Tabelle zusa mme n:
Einfache Applesoft-Variablen Ree ll e Zah l
Ganze Zah l
Zeichenkette
Funktion
Name 1 . Byte 0 2 . Byte 0
Name 1. Byte 1 2. Byte 1
Name 1. Byte 0 2. Byte 1
Name 1 . Byte 1 2. Byte 0
Expo nent Man ti sse MSB Ma nti sse Mant i sse Mant i sse LSB
Wert Lo-Byte Wert Hi-Byte
Längen-Byte Adresse Lo- Byte Adresse Hi-Byte
Lo-Adr. Hi -Adr. Lo- Adr. Hi- Adr. Zeichen
00 00 00
00 00
nach nach Var i ab. Variab. nach =
Die Feldvariabl en (auch Ma trizen genannt) li egen oberh alb der einfachen Vari abl en. ARYTAB ($006B/6e) zeigt auf de n A nfang de r Feldva ri a blen, STR END ($006D/6E) auf das E nde. Di e Fe ldva ri ab len we rde n genauso bezeichnet wie di e einfachen Va ri ablen, nur das hinter die Beze ichnung noch eine Klammer gesetzt wird. Diese enthält eine Index-Liste , d ie aus durch Ko mma getrennte n num erischen A usdrücken für jede Dimension besteht . Von jedem numerischen A usdruck wird nu r der ga nzzahlige A nteil a ls Index ausgewertet (z. B. A$ (1 ,2,1.1 +4) = A$(1 ,2,5)) Die Länge der E intrag ungen für Feldva riablen ist unterschiedlich. E in E intrag enthält zunächst die ersten be iden Bytes des Na mens, wo bei de r T yp ge nauso
6. Und immer schön variabel bleiben!
126
codiert ist wie bei den einfachen Variable n. Der Funktio ns-Typ entfällt. Im 3. und 4. Byte steht ein sogenan nter Offset-Zeiger. Er gibt an , wi eviele Bytes zum Anfang dieser Tabelle addiert werden müssen , um zum Begin n der nächsten Tabelle zu gelangen. Diese Information ist wichtig, wei l alle Tabellen unte rschied lich lang sein können. Das 5. Byte e nthält die Zahl der Dimensionen . Für jede Dimension folgen jetzt 2 Bytes , die die G röße der Dimension angeben. Diese Bytepaare beginnen mit der am weitesten rechts stehenden Dimension (bei A(1,2 ,3) also mit 3). Der soeben besprochene Teil der Tabelle wird auch Struktur- oder I nformationsb lock (= Variablen-Kopf) genan nt. E r ist für alle Variable nt ypen gleich aufgebaut. Es schließt sich der Werteblock an , in dem eine reelle Za hl 5 Bytes, eine ganze Zahl 2 Bytes un d eine Zeichen kette 3 Bytes belegt. Jeder Eintrag entspricht dem der einfachen Variablen. Im Gegensatz zu den einfachen Variable n gibt es bei den Feldern aber kein Auffüllen mit Nullen. Bei mehrdimensionalen Fe ldern sind die Werte im Werteblock so angeordnet , daß der am weitesten rechts ste hende Index am langsa msten anwächst. Fassen wir a uch diesmal a lle Informatione n in einer Tabelle zusammen:
Applesoft Feldvariablen Ganze Zahl
Zeichenkette
Name 1. Byte 1 2 . Byt e 1
Name 1. Byte 2. Byte 1
Offset Lo-Byte Offset Hi-Byte
Offset Lo-Byte Offset Hi-Byte
Offset Lo-Byte Offset Hi-Byte
Dimensionen
Dimensionen
Dimensionen
Reelle Zahl Name 1. Byte 2. Byte
°° N
N
° N
Lo-Größe Dirn. N Hi-Größe Dirn. N
Lo-Größe Dirn. N Hi-Größe Dirn .. N
Lo-G röße Dirn . N Hi-G röße Dirn . N
Lo-Größe Dirn. Hi-Größe Dirn.
Lo-Größe Dirn. Hi-Größe Dirn.
Lo-G röße Dirn. Hi-Größe Dirn.
°°
°°
°°
---------------------------------------------------Wert von (0,0 , . . 0 ) Wert von (0 , 0, . . 0 ) Stringzeiger (0 , 0, . .0 )
Wert Lo-Byte Wert Hi- Byte
Exponent Manti sse MSB Mantisse Mantisse Mantisse LSB
--_._ --------
-----------Wert von (1, 0 , . . 0)
- -----------
Wert von (1, 0 , .. 0) Wert Lo-Byte Wert Hi -Byte
Exponent Mantisse MSB ------------
Län gen-By te Adresse Lo-Byt e Adresse Hi-Byte
------------
Stringzeiger ( 1 , 0, . 0 ) Längen-Byte Adresse Lo-Byte Adresse Hi-Byte ------------
------------
------------
6.2 Wer suchet, der findet
127
------------
Wer t vo n (N , N, . . N) Exponent Mantisse MSB Manti sse Mant i sse Man ti sse LSB
Wert von (N,N, .. N) Wert La- Byte Wert Hi- Byte
Stringzeiger (N,N , . . N) Lä ngen-Byt e Adre sse La-Byte Adresse Hi-Byte
Wie wir sehen kö nn en , stehen numerische Werte di rekt in de n Tabelle n. Bei de n Zeichen ke tte n sind do rt nu r Zeiger gespeichert.
6.2 Wer suchet, der rmdet A pplesoft besitzt eine Ro utine, die es un s ermöglicht , eine Va ri able im Speicher zu fin den . PTRGET ($DFE3) kan n sowoh l für einfac he als auch für Fe ldvari ablen ben utzt werden. Z uvo r mu ß TXTPTR ($00B8/B9) auf de n 1. Buchstaben des Va ri ablenn amens ze igen. Mit der Speicherstell e SUBFLAG ($0014) können wir noch festlegen, ob auch Ganzzahl-Variable (INTEGER) ges ucht we rden so llen. Ist Bit 7 vo n SUBFLAG gesetzt, sind Ganzzahl-Vari able ausgeschlossen. PT R GET hat eine Vielzahl vo n E rgebnissen. Gehen wir zunächst davo n aus, daß die Va ri ab le bereits existiert . Dann zeigt V ARPNT ($0083/84) auf di e Speicherad resse des Variablenwertes (nicht auf de n Namen! ) . Bei reellen Zahlen ist das der Exponent, bei ganzen Zahlen das Lo-Byte un d be i Zeichenke tten das Längenbyte . Das Lo-Byte dieser Adressse ste ht zusätzlich im Akk umul ato r, wä hre nd sich das Hi-Byte im Y-Register befinde t. LOWTR ($009B/ 9C) zeigt auf das 1. Namensbyte, wä hrend beide Bytes mit entsprechend gesetzten/gelöschten Bi ts 7 nach VARNAM ($0081/82) übertragen wurden . VALTYP ($0011) ist $00 bei ein er numerischen Va riabl en und $FF bei einer Zeichen kette. NUMTYP ($0012) ist $00 bei einer reellen Zahl und $80 be i einer Ganzzahl. NUMDIM ($OOOF) ist $00 bei einer Feldvariablen, sonst <> $00. FLENGTH ($0064) bein haltet bei Feldvariab len die Eintragslänge (2/5/3 für Ganzza hllReelle ZahllZeichenkette) und HIGHDS ($0094/95) zeigt - e benfa lls nur bei Feldvariablen - auf den ersten E intrag im We rte block de r Tabe lle . Existiert die Va riable beim A ufruf vo n PTRGET noch ni cht , wird sie angelegt
128
6. Und immer schön variabel bl eiben!
und auf Null initi alisiert. Bei Feldvariablen geschieht di es mit einer Dimensioni erung vo n 10 für jeden Index. War allerdings ein er der Indizes beim Aufruf schon größer als 10, so erfolgt die Fehlermeldung "BAD SUB SCRIPT E RROR". Diese Fehlermeldung erschein t im übrigen auch, wenn eine Feldvariable vo n PTRGET gesucht wird , zu der vorher nur eine kleinere Matrix defini ert wurde. Wenn Sie verhindern wollen, daß eine Va ri able neu angelegt wird , müssen Sie in SUBFLAG das Bit 6 setzen (z .B. $40). Vergessen Sie aber nicht, es später wieder zurückzusetzen, denn ein fo lgendes "INPUT" von Applesoft aus würde sonst nicht mehr funktionieren. Speziell für Feldvariablen gibt es noch eine zweite Lokalisierroutine bei $F7D9 mi t dem Namen GET ARYPT. Auch hier muß TXTPTR auf das 1. Namensbyte zeigen. Ist die Vari able nicht vo rhanden, wird sie nicht angelegt, sondern eine Fehlermeldung ausgegeben. Wird die Vari able gefund en, so zeigt LOWTR ($009B/9C) auf das 1. Byte des Namens im Strukturblock (Kopf) .
PTRGET $DFE3 Sucht eine Variable (außer Funktionen! )
Eingabe: TXTPTR ($00B8/B9) zeigt auf 1. Na mensbyte SUBFLAG ($0014) = $00, Bit 7 setzen, um Ganzza hlen zu sperren, Bit 6 setzen, um Neuanl age zu verhindern Ausga be: Akku = Vari ablenwe rt Lo , Y-Reg = Vari ablenwe rt Hi VARPNT ($0083/84) zeigt auf Vari ablenwert (Lo/Hi) LOWTR ($009B/9C) zeigt auf 1. Namensbyte VARNAM ($0081/82) enth ält den Vari ablennamen VALTYP ($0011) = $00 bei numerischen Var. , = $FF bei Zeichenkette NUMTYP ($0012) = $00 bei ree ller Zahl , = $80 bei Ga nzzahl NUMDIM ($OOOF) = $00 bei Feldva riablen, sonst <> $00 FLENGTH ($0064) Eintragslänge bei Feldvariab len HIGHDS ($0094/95) Zeiger auf Beginn des Werte blocks
6.3 H in und her , das fällt nicht schwer
129
GETARYPT $F7D9 sucht Vari ablen kopf einer Feldvariablen E ingabe : TXTPTR ($OOB8/B9) zeigt auf 1. Namensbyte Ausgabe: LOWTR ($009B/9C) zeigt auf den Beginn des Strukturblocks (1. Namensbyte)
6.3 Hin und her, das fällt nicht schwer U nser Wissen über die Applesoft-Variablen ist bisher recht theoretischer Natur. In einem kleinen Demonstrationsprogramm wollen wir jetzt üben , mit einem Maschinensprache-Prog ramm Inhalte von Variabl en zu füllen, di e durch ein (gleichzeitig im Speicher befindliches) Appl esoft- Programm angelegt wurden. Anschließend ve rarbeitet das BASIC-Programm die neuen Werte .
VAR-DEMO 10 PRINT CHR $ (4)"BRUN VAR-DEMO.OBJ " 15 PRI NT CHR$ (21) 20 TEXT HOME VTAB 2: HTAB 8 : PRINT "VARIABLEN DEMONSTRATION" 30 VTAB 5 : PRI NT "GEBEN SIE EINE ZAHL ZWISCHEN EINS UND" : PRINT "NEUN EIN: " ;: GET Z$:Z = VAL (Z$) : IF' Z < 1 THEN PRINT CHR $ (7) : GOTO 30 40 PRINT Z: POKE 254,Z 50 VTAB 8: PRINT "GEBEN SIE EIN BELIEBIGES DRUCKBARES " : PRINT "ZE I CHEN EI N: ";: GET Z$:Y = ASC (Z$): IF' Y < 32 OR Y > 126 THEN PRINT CHR$ (7): GOTO 50 60 PRI NT Z$ : POKE 255,Y 70 Z$ = "-- - - - - - - - - - - - -- - - - - - - - - - - - - - - - - - - - - -- - - - " 80 VTAB 11: PRINT Z$: PRINT PRI NT "JETZIGE VARIABLENWERTE:": PRINT Z$: PRINT PRINT "A%= "A%;: HTAB 10 : PRINT "A = "A;: HTAB 20: PRINT "A $= "A$ 90 PRI NT "C= "C: PRINT "B(A%) = "B(A%): PRINT "C $= "C$: PRINT : PRI NT Z$ 100 PRINT PRINT "GEBEN SIE JETZT ZUNAECHST EI NE F'LIESS- KOMMAZAHL IN DAS LAUF'ENDE MASCHI NENPRO- GRAMM EIN (ENDE =
130
120 125 130 140
6. Und immer schön vari abel bleiben!
PRINT : PRINT Z$ : PRINT : PRINT "NEUE VARIABLENWERTE:": PRINT Z$: PRINT PRINT "A%= "A%;: HTAB 10: PRINT "A = "A ; : HTAB 20: PRINT "A $= "A$ PRINT "C= "C: PRINT "B(A%)= "B(A%): PRINT "C $= "C $ : PRINT : PRINT Z$ PRINT PRINT "ERNEUT ? ";: GET Z$: IF' Z$ = "J" OR Z$ = "j" OR Z$ = "Y" OR Z$ = "y" THEN GOTO 20 END
Das aufgerufene Maschinenprogramm sieht so aus:
VARIABLEN-DEMO 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 9500: A9 00 32 9502: 85 50 33 9504: A9 95 34 9506: 85 51 35 9508: 20 8C F'2 36 950B: 60 37 38 39 40 950C: A5 B8 41 950E: 8D B2 95 42 9511 : A5 B9 43 9513: 8D B3 95 44
;******************************* AS-Variab1en-Zuweisun gen * vom Maschinenp r ogramm au s * Demo-Progr amm * (C) 1985 Jürgen B. Kehr e1 * ;******************************* PROMPT LI NNUM VARPNT F'ORPNT CHRGOT TXTPTR WERT ZEICHEN PUF'F'ER GDBUF'S STRCPY PTRGET SNGF'LT STRLT1 MOVEMF' F'IN RSHIMEM GETLNZ BASE
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
$0033 $0050 $0083 $0085 $00B7 $00B8 $OOF'E $OOF'F' $0200 $D539 $DA9A $DF'E3 $E301 $E3E9 $EB2B $EC4A $F'28C $F'D67 $9500
ORG BASE HIMEM: unter Pro gramm s etzen (DOS 3.3) START
LDA STA LDA STA J SR RTS
#< BASE LINNUM #> BASE LINNUM+1 RSHIMEM
Textpointer von AS retten CALL
LDA STA LDA STA
TXTPTR STXTPTR TXTPTR+1 STXTPTR+1
131
6.3 Hin und her, das fällt nicht schwer
9516: 9518: 951A: 951C: 951 E: 952 1 : 9523: 9524: 9526 : 9527: 9529:
952B: 952D: 9530: 9532: 9534: 9536: 9538: 953B: 953C:
A9 85 A9 85 20 A9 A8 91 C8 A5 91
C8 B8 95 B9 E3 DF 00 83 FE 83
A4 FE
20 A9 85 A9 85 20 AA 20
01 E3 CB B8 95 B9 E3 DF 2B EB
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
953F: 9541 : 9543: 9546: 9549: 954B: 954D 954F 9551 9554 9557 9559 955B 955D 955F 9562 9563
9566 9568 956B 956D 9570
A9 85 20 20 A9 85 A9 85 20 20 A9 85 A9 85 20 AA 20
A5 8D A2 20 A9
Al 33 67 39 00 B8 02 B9 B7 4A D9 B8 95 B9 E3
FD D5
00 EC
DF
2B EB
FF 00 02 01 39 D5 CD
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
Integer-Variable mit WERT füllen LDA STA LDA STA JSR LDA TAY STA INY LDA STA
#INTVAR TXTPTR+l PTRGET #$00
;Textpoi nt er auf ;Variablennamen ;zeigen lassen
;Variable suchen ;Hi-Byte-Wert ;Y=O (VARPNT) , Y ;speichern ; auf Lo-Byte stellen ; Lo-By te-Wert laden WERT (VARPNT) , Y ;speichern
Floating-Point-Variable mit WERT füllen LDY JSR LDA STA LDA STA JSR TAX JSR
WERT SNGFLT # FLOATVAR TXTPTR+l PTRGET MOVEMF
;WERT laden ;in Fließkomma-Zahl ;Textpointer auf ;Variablennamen ;zeigen lassen ;Variabl e suchen ; Lo-By te Adr. nach X ;FAC - > Variable
FP-Variable mit eingegebenem Wert füllen LDA STA JSR JSR LDA STA LDA STA JSR JSR LDA STA LDA STA JSR TAX JSR
* II!II
PROMPT GETLNZ GDBUFS # PUFFER TXTPTR+l CHRGOT F'IN #< FPEING TXTPTR #> FPEING TXTPTR+l PTRGET MOVEMF
;Prompt ändern ;Zeile holen ;Bit7 löschen, Endmarker ;Textpointer auf ;Eingabe zeigen ; l assen ;1 Zeichen im Akku ; Puffer - > FAC ;Textpointer auf ;Variablennamen ;zeigen lassen ;Variable suchen ;X vorbereiten ;FAC - > Variable
1 Zeichen einem String zuweisen LDA STA LDX JSR LDA
ZEICHEN PUFFER #$01 GDBUFS # <STRVAR
;ZEICHEN laden ;in Eingabepuffer ;Stringlänge = 1 ;Bit7 l öschen, "0" Ende ;Textpointer auf
132
9572 : 9574: 9576 : 9578 :
957B: 957D: 957F: 9581 : 9583: 9586: 9588: 958B: 958D: 958F:
9592: 9594: 9596: 9599: 959C : 959E: 95AO: 95A2: 95A4:
95A7 : 95AA : 95AC: 95AF: 95Bl:
95B4: 95B7 : 95B9: 95BB: 95BD: 95BF: 95C l 95C4 95C7
6. Und immer schön variabe l bleiben!
85 A9 85 20
A9 85 A9 85 20 A4 20 A6 A4 20
A9 85 20 20 A9 85 A9 85 20
AD 85 AD 85 60
20 85 84 A9 AO A2 20 20 60
B8 95 B9 B4 95
DO B8 95 B9 E3 DF FE 01 E3 83 84 2B EB
BE 33 67 FD 39 D5 D6 B8 95 B9 B4 95
B2 95 B8 B3 95 B9
E3 DF 85 86 00 02 00 E9 E3 9A DA
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
STA LDA STA JSR
TXTPTR f> STRVAR TXTPTR+l MAKESTR
;Variablennamen ; zeigen l assen ;String herstellen
Arrayindex auch eine Variable LDA STA LDA STA JSR LDY JSR LDX LDY JSR
f< ARVAR TXTPTR f> ARVAR TXTPTR+l PTRGET WERT SNGFLT VARPNT VARPNT+l MOVEMF
; zuerst Textpointer ;auf Variablennamen ;zeigen l assen ;Variable suchen ;WERT l aden ; WERT - > FAC ;Variablenzeiger ;zurückladen ;FAC - > Variable
Stringeingabe speichern LDA STA JSR JSR LDA STA LDA STA JSR
# 11 ) 11
PROMPT GETLNZ GDBUFS f< EINGVAR TXTPTR f >EINGVAR TXTPTR+l MAKESTR
; Prompt-Zeichen ändern ; Zeile holen ;Bit7 löschen , 110 ;Textpointer auf ; Variablennamen ;zeigen l assen
11
;String herstellen
alten Textpointer wieder herstellen LDA STA LDA STA RTS STXTPTR
STXTPTR TXTPTR STXTPTR+l TXTPTR+l
DFS 2
Zeichenkette im Eingabepuffer in den bezeichneten String kopieren MAKESTR
JSR STA STY LDA LDY LDX JSR JSR RTS
PTRGET FORPNT FORPNT+l f< PUFFER f> PUFFER #$00 STRLTI STRCPY
;Variabl e suchen ;Zeiger speichern ;Lo Stringadresse ;Hi Stringadresse ;Endzeichen ;String kopieren ;Descriptor - > Var. ; fertig
Variablennamen, Ende mit
LI : 11
Ende
6.3 Hin und her, das fällt nicht schwer 95C8: 95CB: 95CO: 9500: 9506: 9509:
41 41 41 42 43 43
25 3A 24 28 24 3A
3A 3A 41 3A
154 155 156 157 158 159
INTVAR FLOATVAR STRVAR ARVAR EINGVAR FPEING
133 ASC ASC ASC ASC ASC ASC
'A%: ' 'A: ' 'A$: ' 'B(A%): ' ' C$: ' 'C: '
Das BASIC-Programm startet zunächst das Maschinenprogramm , das seinerseits HIMEM unter sich legt, um sich vor einem Überschreiben durch die BASIC-Variablen zu schützen (nur unter DOS 3.3!) . Sodann liest das BASICProgramm eine Zahl zwischen 1 und 9 und ei n druckbares Ze ichen ein. Die Zahl und der ASCII-Wert des Zeichens werden in die Speicherstellen 254 und 255 ($OOFE und $OOFF) gepoked, um sie dort zwischenzuspeichern . Im Anschluß daran werden alle Variab len mit ihrem augenblick lichen Inhalt angezeigt, damit Sie sehen können, daß Ihre Eingaben dort noch nicht angekommen sind. Nach der Ausgabe einer entsprechenden Aufforder ung wird mit dem CALL in die Speicherstelle $950C gesprungen . Nach dem Ab lauf des Maschinenprogramms zeigt das BASIC-Programm erneut die Variablen-Werte, um Ihnen zu beweisen, daß jetzt die neuen Inhalte angekommen si nd. Sie kön nen die Demo immer wiederholen. Derfür uns jetzt interessantere Tei l li egt im Assembler-Programm. Dieses rettet zunächst den App lesoft-Textzeiger TXTPTR, um ihn später wieder herstellen zu können. Würde dies nicht geschehen, könnte das BASIC-Programm abstürzen . Da die Variablen mit PTRGET gesucht werden sollen, muß nämlich TXTPTR auf den Variab lennamen umgesetzt werden. Die Variablen namen stehen am Programmende in ein er Tabelle. Jeder Name muß mit dem Tren nzeichen ,,:" beendet werden , damit PTRGET die richtige Name nslänge erkennt. In Ihren eigenen Programmen müssen die Namen nicht fest vorgegeben sein . Es genügt, sie an eine definierte Stell e zu sch reiben , was auch in einem laufenden Programm geschehen kann. Zuerst soll die Ganzzahl- Variable "A %" gefüllt werden. Wir stellen deshalb TXTPTR auf den Namensanfang und rufen PTRGET auf. VARPNT zeigt anschließend auf den Variab lenwert innerhalb der Tabe ll e. Als Zahlenwert wollen wir die Zahl nehmen , die vom Applesoftprogramm in der Speicherstelle $OOFE (254) abge legt worden ist. Da diese nur 1 Byte benötigt, muß das Hi-Byte der Variablen auf Null gesetzt werden . Durch die indirekte indizierte Adressierung werden die bei den Wert-Bytes direkt in die Variable geschrieben (Zeile 53 - 58). Dieselbe Zahl so ll anschließend als Fließkomma-Zah l in .. A" untergebracht werden. Mit SNGFLT wird sie in eine ungepackte Fli eßkoml113-Zahl im MFAC
134
6. Und imm er schön variabel bleiben!
verwandelt . Der Textpointer wird auf den neuen Namen umgesetzt und PTRGET findet wieder de n richtigen Speicherplatz. Mittels MOVEMF wird die Fließkomma-Zah l gepackt und dann auf den Speicherplatz der Variablen transportiert. MOVEMF erwartet das Lo-Byte der Zieladresse im X-Register und das Hi-Byte im Y-Register. PTRGET hat dies für das Hi-Byte auch vorbereitet, den Lo-Wert aber im Akk umul ator übergeben. E in TAX (Zei le 89) sorgt hier für die Anpassung. Ei ne über die Tastatur eingegebene Za hl soll in "C" gepeichert werden. Wir benutzen die Routine GETLNZ ($FD67), um alle Zeichen von der Tastatur bis zum abschließenden RETURN zu speichern. GETLNZ gibt zunäch st ein $8D (= RETURN) über COUT aus und danach das Zeichen, das in PROMPT ($0033) enth alten ist. Wir haben PROMPT in diesem Fall vorher mit ei nem Ausrufezeichen gefü ll t. All e Zeichen von der Tastatur (max. 255) werden nacheinander ab $0200 mit gesetztem Bit 7 abgelegt, wobei das X-Register die Anzahl mitzählt.
GETLNZ $FD67
Gibt ei n RETURN und den Inhalt von PROMPT über COUT aus. Ein e Ei ngabe wird über den Vektor KSWLlH ($0038/39) bis zu einem abschli eßenden RETURN geholt und in den Tastaturpuffer ab $200 mit gesetzte m Bit 7 abgelegt. Eingabe: PROMPT ($0033) = $AO - $FE Ausgabe: Ab $0200 Eingabestring X-Reg = Eingabelänge (zeigt auf $8D)
GETLN $FD6A
Wie GETLNZ, nur wird kein RETURN zu Beginn ausgegeben. Eingabe: PROMPT ($0033) = $AO - $FE Ausgabe: Ab $0200 Eingabestring X-Reg = Eingabe länge (ze igt auf $8D)
6.3 Hin und he r, das fä ll t ni cht schwer
135
GETLNI $FD6F Wie GETLNZ , nur wird weder RETURN noch PROMPT zu Beginn ausgegeben. E ingabe: A usga be : Ab $0200 E in gabestrin g X-Reg = E ingabelänge (zeigt auf $8D)
Die App lesoft-Routin e GDBUFS ($D539) löscht bei der im X-Register übergebenen A nza hl vo n Bytes im Tastaturpuffer die Bits 7 und hängt ein $00 als Endkennzeichnung der E ingabe an. In diesem Fall wird das $8D durch $00 überschrie ben.
GDBUFS $D539 Fügt $00 als End marke an di e E in gabe im Tastaturpuffer und löscht in alle n Bytes das B it 7. E ingabe: X-Reg = Anzahl der Bytes Ausgabe : Akku = $00 , X-Reg = $FF, Y-Reg = $01
Die Zeichenkette im Puffer, die die gewünschte Zahl darstellt , ist noch ASCIIkodiert. Wir müssen sie in eine Fließkomm a-Zahl umwandeln. Der ApplesoftInterpreter stellt uns dafür FIN ($EC4A) zur Verfüg un g, das einen Zahl enstring in eine FP-Ko nsta nte im MFAC um wandelt . Vo r dem A ufruf vo n FIN mu ß TXTPTR auf das erste Stringzeichen weisen , und mit einem JSR CHRGOT ($00B7) muß dieses 1. Ze iche n in de n Akk umul ato r geholt werden.
136
6. Und immer schön vari abel bleiben!
FIN $EC4A Ve rwa ndelt Z ahlenstring in FP-Konstante im MFAC Ei nga be: TXTPT R ($ 00B8/B9) ze igt auf 1. Stringze ichen A kku = 1. Stringzeichen A usga be: FP-Konstante im MFAC TXTPTR zeigt hinter Zahlenstring
Jetzt wird der TXTPTR auf den Variablenn amen umgesetzt und mit PTRGET in bekannter Mani er die Va ri able gesucht. MOVEMF transportiert dann die Fließkommaza hl in ge packter Form vo m MFAC in die Va riable. U nsere nächste A ufgabe besteht darin , ein ASCII-Zeichen aus de r Speicherstelle $FF (255) in die Va ri able "A$" zu bringe n. Es wird dazu aus sein er Speicherstell e in den Tas tatureinga be-Puffe r nach $0200 kopiert. GDBUFS löscht B it 7 und hängt ein $00 an. D er Textpointer TXTPTR wird wieder auf den Vari ablen namen gesetzt und die U nterroutin e MAKESTR aufge rufen, die die Z eichen kette im Tastatur-Puffer bis zum abschließenden $00 in den bezeichneten String kopiert. A uch hi er setzen wir PTR GET ein , nur daß wir die Zeiger auf die Va ri able zunächst nach FORPNT und FORPNT+ 1 zwischenspeichern. Die Routine STRLTl ($E3E9) bestimmt die Länge des Strings anh and des im X-Register überge benen E ndmarkers. We nn der String auf der Zero-Page oder im Tastatur-Puffe r steht , wird er in den Stringpool unterhalb vo n FR ETOP kopiert und FRETO P nach unten gesetzt. E in Deskriptor für den String wird angelegt und auf den sogenannten "Deskri ptore n-Stack " zu r Z wischenspeicherung geschoben. TEMPPT ($0052) ist der Zeiger ("Stackpointer") im Deskrip to renstack , der entsprechend ko rrigiert wird. We nn wir aus ein em BASIC-Programm kommen, brauchen wir ihn nicht zu initi ali sieren.
6.3 Hin und her , das fä llt nicht schwer
137
STRLTl $E3E9 Bestimmt Stringlänge an hand des Endmarkers. Wenn der String in Seite 0 oder 2 li egt, wird er in den Stringpool kopiert . E in Deskpritor wird auf dem Deskriptoren-Stack ange legt. Eingabe: X-Reg = E ndmarker , Akk u = Lo-Adresse String Y-Reg = H i-Adresse String, TEMPPT = Deskr. rStack-Zeiger Ausgabe: TEMPPT um 3 heraufgesetzt (= X-Reg) FRETOP gegebenenfa lls versetzt VALTYP ($0011) = $FF bei String VPNT ($00AO/A1) zeigt auf Deskr.-Stack STRNG2 ($OOAD/AE) ze igt hinter den String
Vom Deskriptoren-Stack müssen die drei Bytes des String-Deskriptors noch in die Variable gebracht werden. STRCPY ($DA9A) besorgt dies für uns, wenn FORPNT ($0085/86) auf die Variab le und VPNT ($00AO/A1) auf den Deskriptor ze igt. VPNT wurde durch STRLTl richtig gesetzt , und FORPNT erhi elt seine Werte bereits in Zei le 143/44.
STRCPY $DA9A Überträgt Deskriptor in die Variab le E ingabe : FORPNT ($0085/86) zeigt auf Variable VPNT ($OOAO/Al) zeigt auf Deskriptor Ausga be: -
U nser näc hstes Z iel ist es, ei ne Feldvariab le zu fü llen , deren Index auch wieder eine Variable ist. Die Adresse der Variab len wird in der bekann ten Weise über PTRGET ges ucht. Anschl ießend wird ihr Inh alt aus der Speicherstell e $OOFE (254) geladen. Da wir als Typ ei ne reelle Variable gewähl t haben, muß der Wert in ein e Fließkomma-Zahl umgewandelt werde n. SNGFLT "floatet" das Y -Regi-
138
6. Und immer schön variabel bleiben!
ster nach MFAC und MOVEMF beso rgt erneut den Transport in die Variab le. x- und Y-Register müssen hierbei neu mit der Zieladresse ge laden werden, da die beiden voranstehenden Befehle di e von PTRGET im Akku und im Y-Register übergebenen Werte zerstört haben. VARPNT, das dieselbe Inform ation enthält , ist aber erh alten ge blieben. Ein en beli eb igen String von der Tastatur zu lesen, fä llt nun nicht mehr schwer. GETLNZ nimmt wieder unse re Eingabe entgegen, GDBUFS löscht Bit 7 und setzt den Endmarker $00, wä hrend die Unterroutine MAKESTR in der schon beschriebenen Art und Weise di e Zeichen kette aus dem Tastatur-Puffer in den bezeichneten String kopiert. Zum Abschluß der Demonstration wi rd TXTPTR auf seinen alten Wert zu rückgesetzt und nach BASIC zurückgekehrt. In di ese m Demonstrationsp rogramm sind fast alle gebräuchli chen Fä lle vorgekomm en, so daß Sie für Ihre Programme die richtigen Tei le nur herauszupicken brauchen. Eines der schwierigsten Probleme im Zusa mmenspiel von Assembler und Applesoft ist damit auf einfache Weise zu lösen.
6.4 Stühlerücken Weil wir jetzt wissen, wie Variablen des Applesoft aufgebaut sind und wie wir sie im Speicher loka lisieren können , schreiben wir uns nun ei n paar nützliche Anwendungen. Wenn Sie in einem BASIC-Programm zwei Variablen miteinander tauschen wollen (z.B. A$ und B$) , müssen Sie immer einen Ringtausch programmi eren: T$
=
A$
A$ = B$ : B$ = T$
Das geht relativ langsam , was aber zumeist nicht sehr störend ist. Gravierender ist die Tatsache, daß ein so lcher Ringtausch viele sogenannte "Stringleichen" erzeugt, da Applesoft für jede Neuzuweisung an einen bestehenden Variab lennamen einen neuen Eintrag im Stringpoo l macht. Damit füllt sich der Speicher und Ihr Programm legt ein e Zwangspause ein , um alles wieder aufzurä um en. Viel eleganter ist es da doch, in einem Maschinenprogramm die bei den Va ri ablen zu suchen und direkt ihre Eintragungen zu vertauschen. Wi r wollen di eses Programm SWAP nennen. Damit wir es auch von Applesoft aufrufen können, müssen wir un s noch eine bequeme Übergabe ausdenken.
6.4 Stühlerücken
139
Die Programmie rer vo n Applesoft-B ASIC haben in den Interpreter mit dem &-Befe hl (= Ampersa nd) bereits ein e Möglichkeit einge baut , zusätzli che Maschi nenroutine n aufzurufe n . Immer wenn der Inte rpre ter auf ein nicht in Anführu ngszeichen oder nach eine m REM stehenden &-Zeiche n im Progra mm trifft , macht er einen Sprun g nach $03FS . Dort steht no rm alerweise ein JMP $FF58. Bei $FF58 im Monitor ste ht ein RTS , das uns wieder ins Applesoft-Programm zurückbefördert. Wenn wir alles so beließen , hätte dieser Sprung keine A uswirkunge n . Wir kö nn e n abe r das JMP $FFS8, da es im RAM ste ht , a uch verä nde rn und in ein von uns geschriebe nes Masch ine nprogramm umlenke n . Von dort ke hre n wir dann nach geta ne r Arbeit mit eine m RTS zur ück in s laufende Applesoft-Programm. Dieser "Trick " ist ausreiche nd, we nn wir keine weitere Information zwische n BASIC und de m Masch in e nprogramm zu übe rgebe n habe n. Unserer Routin e SWAP müssen wir abe r di e Na me n de r zwei zu verta uschende n Variablen ne nn en . U m die notwend ige Parameterübergabe zu verste he n , müsse n wir zun ächst erklären , wie Applesoft das BASIC-Program m liest. Beim Kaltstart des Rechners wird aus dem ROM von $F10B nach $00B1 bis $00C8 ein klein es Programm kopiert, die CHRGET-Routine ($00B1), zu der auch de r Textpo inte rTXTPTR gehört. CHRGET hat zwe i E insprünge : bei $00B1 wird zunächst der TXTPTR um 1 erhöht und da nn der Akk umul ato r mit dem Byte vo n derTextpointer-Ste lle geladen. Bei $00B7 (= CHR GOT) wird der Akkumu lato r geladen , o hn e daß vor her der Textpointe r weitergesetzt wurde.
CHRGET $00B1 Erhöht TXTPTR und läd TXTPTR-Stelle in den Akk u. Leerze iche n ($20) werden übersprungen. Testet Zeichen . Ei ngabe: A usgabe: Akku = gelesenes Zeichen Carry-Bit = 1 => Ziffer Carry-Bit = 0 => so nst. Zeiche n Zero-Bit = 1 => " oder $00 Zero-Bit = 0 => weder " noch $00
6. Und immer schön vari abel bleiben!
140
CHRGOT $008 7 Läd Akku von der TXTPTR-Stelle. Leerzeichen ($20) werden übersprungen. Testet Zeichen.
E ingabe: Ausgabe: Akku = gelesenes Zeichen Carry-Bit = 1 ~ Ziffe r Carry-Bit = 0 ~ so nst. Zeichen Zero-B it = 1 ~ " oder $00 Zero-Bit = 0 ~ weder " noch $00
Wenn nun Applesoft auf ein & trifft , springt es nicht nur nach $03F5, sondern führt auch noch ein JSR CHRGET aus, so daß sich das auf & fo lgende Zeichen im Akkumul ator befind et und TXTPTR hinter das & zeigt. Mit diesem Wissen kö nnen wir jetzt eine Routine schreiben, die alle nach dem & stehenden Zeichen als Parameter auswertet . SWAPI 1 2 3 4 5 6 7 8 9 10 11
0300 0302 0305 0307 030A : 030C : 030 F :
A9 80 A9 80 A9 80 60
4C F5 03 10 F6 03 03 F7 03
03 10 : 0313: 031 5 03 17 03 19
20 85 84 A5 48
E3 DF 85 86 81
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
;******************************* Variablen- Tausch e r SWA PI * ;******************************* VARNAM VARPNT FORPNT AMPER OATA MI SMTCH CHKCOM PTRG ET
EQU EQU EQU EQU EQU EQU EQU EQU
$0081 $0083 $0085 $03 F5 $0995 $0076 $OEBE $OFE3
;+ $0082 ; + $0084 ;+ $0086
ORG $0300 LOA U 4C STA AMPER LOA * <START STA AMP ER+l LOA *> START STA AMPER+2 RTS START
JSR STA STY LOA PHA
PTRGET FORPNT FORPNT+l VARNAM
;JMP ; Ampersand Sprung; vektor setz en
; 1. Var i abl e ;Lo ; Hi Adresse ;1. Name nsze i chen ;retten
6.4 Stühlerücken 031A: 031C: 031D: 0320: 0323: 0324: 0326: 0328: 0329: 032B: 032D: 032F': 0331 : 0332 : 0334 : 0336 : 0337 : 0339: 033A : 033C:
A5 48 20 20 68 45 30 68 45 30 AO BI AA BI 91 8A 91 88 10 4C
82 BE DE E3 DF' 82 17 81 12 04 83 85 83 85 F'3 95 D9
033F': 4C 76 DD
141 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
LOOP
MISMATCH
LDA PHA JSR JSR PLA EOR BMI PLA EOR BMI LDY LDA TAX LDA STA TXA STA DEY BPL JMP
VARNAM+l CHKCOM PTRGET VARNAM+l MISMATCH
; 2. Namenszeichen ;retten ; 2. Vari able ; alter Name ;gleicher Typ?
;dito VARNAM MISMATCH ;geht nicht #$04 ;5 Bytes (VARPNT) , Y ;retten (F'ORPNT) , Y (VARPNT) , Y ; l. Hälfte (F'ORPNT) , Y ; 2. Hälfte LOOP DATA
JMP MISMTCH
; zum nächsten Be f ehl ;F'ehlermeldung
Die Zeilen 16 bis 22 stellen ein Startprogramm dar , das den Ampersand-Vektor auf den Begi nn des eigent lichen Programms (START) umsetzt. Dies muß nu r ein einziges Ma l geschehen, z.B . indem SWAP1mitteis BRUN gestartet wird . Bei jedem &-Zeichen springt dann der Interpreter nach START. Für den Aufruf vere inbaren wir folgende Syntax: & l.Variable, 2.Variab le. Wie wir wissen , zeigt TXTPTR auf das erste Zeichen nach dem &, hier also auf de n Beginn des ersten Variab lennamens. Wir können deshalb direkt PTRGET aufrufen , um die Va riab le zu finden. Die gefundene Ad resse speichern wir wieder nach FORPNT zwischen , während der Variab lenname (d ie bei den signifikanten Zeichen) auf den Stack gerettet wird (Z. 25 - 30). Auch PTRGET setzt den TXTPTR weiter, de r nun auf das Komma zeigt . CHKCOM ($DEBE) prüft das Vorhandensei n des Kommas und gibt im Fehlerfa ll ei n "SYNTAX ERROR" aus. Mit PTRGET suchen wir dann auch die zweite Variable. Da wir nur Variab len gleichen Typs vertauschen können, wird die Überei nstimmung anh and der Bits 7 geprüft. Wen n das erste und das zweite Na mensbyte jeweils paarweise miteinander EOR-verkn üpft werden , muß das Negativ-Bit im Statusregister gelöscht werden, da sich bei Gleichheit nie eine 1 ergeben kann. Bei Nichtübereinstimmung wird ein "TYPE MISMATCH ERROR" ausgegeben, den wir direkt im ROM aufrufe n.
142
6. Und immer schön variabel bleiben!
CHKCOM $DEBE Prüft , ob TXTPTR auf ein Komma ($2C) zeigt Eingabe: TXTPTR zeigt auf zu prüfendes Zeichen Ausgabe: Falls ja: führt CHRGET aus Fa ll s nein: Fehlermeldung "SYNTAX ERROR"
CHKOPN$DEBB Prüft , ob TXTPTR auf eine geöffnete Klammer ($28) zeigt Eingabe: TXTPTR zeigt auf zu prüfendes Zeichen A usgabe: Falls ja: führt CHRGET aus Falls nein: Fehlermeldung "SYNTAX ERROR"
CHKCLS $DEB8 Prüft , ob TXTPTR auf eine geschlossene Klammer ($29) zeigt Ei ngabe: TXTPTR zeigt auf zu prüfendes Zeichen Ausgabe: Fa lls ja: fü hrt CHRGET aus Falls nein: Fehlermeldung "SYNTAX ERROR"
6.4 Stühlerücken
143
SYNCHR $DECO Prüft , ob das Zeichen unter dem TXTPTR und der Akkumulator übe reinstimme n. E ingabe: TXTPTR zeigt auf zu prüfendes Zeichen Akku = Vergleichszeichen Ausgabe: Falls ja: führt CHRGET aus Fa lls nein: Feh le rmeldung "SYNTAX ERROR"
Um die Inhalte unserer zwe i Variablen zu tauschen, werden in eine r Schleife (Zeile 39 - 47) die 5 Bytes des Variablenwertes ve rtauscht , wobei uns das X-Register als Zwischenspeicher die nt. Unser Progra mm e ndet mit eine m Sprung nach DATA ($D995), das den TXTPTR bis zum nächsten ,,:" oder bis zum Ende der BASIC-Zeile vorsch ie bt un d dann mit RTS endet. A uf di ese Weise gelangen wir in unser aufrufendes BASIC-Programm zurück .
DATA $0995 Schiebt TXTPTR bis zum Befehlsende ($3A oder $00) weiter E ingabe: Ausgabe: T XTPTR a uf nächstes $3A oder $00 gesetzt
D a mit Sie SWAP auch gleich be nutzen können , folgt ein kurzes Demo-Progra mm.
SWAP1.DEMO 1 REM **** SWAP 1 - DEMO **** 5 HOME 10 PRINT CHR$ (4)"BRUN SWA Pl.OBJ" 20 A$ = "EINS":B $ = "ZWEI" 30 PRINT "A $="A $" B$="B$: GOSUB 130 40 & A$,B$ 50 PRINT "A$="A$ " B$="B$ 60 A = 123.45:B = 678.9 1 70 PRINT: PRINT "A="A" B="B: GOSUB 130 80 & A,B
144
6. Und imme r schön variabel bleiben!
90 PRINT "A="A" B="B 100 PRINT PRINT LI ST 110 ,120 110 REM JETZT FEHLER: 120 & A$,B 130 INVERSE: PRINT" SWA P ": NORMAL: RETURN Wie Sie leicht ausprobieren kö nnen , funkt io niert der Tausch sowoh l der beiden Zeichen ketten als auch der Fließkomma-Zah len . Erst in Zeile 120 erha lten wir eine Fehlermeldung , da beide Variablen nicht zum selben Typ gehören. Nebenbei bemerkt: das BASIC-Programm hat noch einen weiteren Fehler , da der Ablauf in die Unterroutine 130 führen und dort einen "Return without Gosub"Fehler bewirken würde. Dazu kommt es allerdings nicht , da bereits der Fehler in Zeile 120 das Programm zwangsweise beendet. Unsere Swap-Routine ist schon ganz praktisch, allerdings versagt sie bei Feldvariablen. Wie Sie aus Kapitel 6.1 wissen, sind bei Feldvariablen die Einträge unterschied lich lang, sodaß unser Austa usch von 5 Bytes nur für ree lle Zah len funktionieren, dagegen bei Zeichen ketten und Ganzzahlen Unordnung stiften würde. Mit einer kleinen Programmänderung können wir aber auch diesen Mangel noch beheben.
SWAP2
1 2 3 4 5 6 7 8 9 10 11
0300: 0302: 0305: 0307: 030A: 030C: 030F:
A9 8D A9 8D A9 8D 60
4C F5 03 10 F6 03 03 F7 03
0310: 0313 0315 0317
20 85 84 A5
E3 DF 85 86 81
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
;******************************* Variablen-Tauscher SWAP2 * ;******************************* FLENGTH VARNAM VARPNT FORPNT AMPER DATA MISMTCH CHKCOM PTRGET
EQU EQU EQU EQU EQU EQU EQU EQU EQU
$0064 $0081 $0083 $0085 $03F5 $D995 $DD76 $DEBE $DFE3
;+ $0082 ;+ $0084 ;+ $0086
ORG $0300
START
LDA STA LDA STA LDA STA RTS
U4C AM PER <START AMPER+l t>START AMPER+2
J SR STA STY LDA
PTRGET FORPNT FORPNT+l VARNAM
*
;JMP ;Ampersand Sprung;vektor setzen
1. Variable Lo Hi Adresse 1. Namenszeichen
6.4 Stüh lerücken
0319: 03 1A: 03 1C: 031D: 0320: 0323: 0324: 0326: 0328: 0329: 032B: 032D: 032F : 0330 : 0332: 0333 : 0335: 0337: 0338: 033A: 033B: 033D:
48 A5 48 20 20 68 45 30 68 45 30
82 BE DE E3 DF 82 18
81 13 A4 64 88 BI 83 AA BI 85 91 83 8A 91 85 88 10 F3 4C 95 D9
0340: 4C 76 DD
145
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
LOOP
MISMATCH
PHA LDA PHA JSR JSR PLA EOR BMI PLA EOR BMI LDY DEY LDA TAX LDA STA TXA STA DEY BPL JMP
VARNAM+l CHKCOM PTRGET VARNAM+l MISMATCH VARNAM MISMATCH FLENGTH
;retten ; 2. Namenszeichen ;retten ; 2. Variable ;alter Name ; glei cher Typ? ;dito ;geht nicht ;2/3/5:INT/STR/REAL
(VARPNT), Y ;retten (FORPNT) , Y (VARPNT),Y ;l. Hälfte (FORPNT), Y ; 2. Hälfte LOOP DATA
;zum nächsten Befehl
JMP MISMTCH
; Fehlermeldung
Die Modifikation ist nur gering, aber sehr wirkungsvoll. PTRGET legt bei Feldvariablen (nur dort!!) in der Speicherstell e FLENGTH ($0064) die Länge des Eintrags ab. Wir benutzen diesen Wert, um unsere Sch leife zu initialisieren. Auch hier soll Ihnen wieder eine Demo zeigen, daß unser Programm erfo lgreich arbeitet.
SWAP2.DEMO 1 REM **** SWAP2 - DEMO **** 5 PRINT CHR $ (4) "BRUN SWAP2.0BJ" 10 HOME : DlM A(2) 20 A(l) = 10:A(2 ) = 20: PRlNT A(l)" 30 & A( 1) , A(2) 40 PRlNT INVERSE: PRINT" SWAP 50 PRlNT: PRlNT A(l)" "A(2) 60 END
"A (2) NORMAL
Acht ung: SWAPI nur für einfache Variablen, SWAP2 nur für Feldvariablen benutzen!
146
6. Und imm er schön va ri abel bleiben!
6.5 Etwas Ordnung kann nicht schaden Mit der Routine SWAP haben wir schon einen wichtigen Tei l für ein Sortierprogramm geschrieben. Wir wollen hier keine allzu komplizierten Algorithmen entwickeln , sondern ein einfaches und kurzes Programm benutzen, das auf der Seite 3 Platz hat und einfach indizierte Zeichen ketten-Felder aufsteige nd nach ihren ASCII-Werten sortiert. Wir verwenden einen Blasen- oder "Bubble"-Sortieralgorithmus, der zwar nicht übermäßig schnell , dafür aber einfach zu verstehen ist.
Abb. 9: " Bubble"-Sort
6.5 Etwas Ordnung kann nicht schaden
147
Ein BASIC-Programm könnte folgendermaßen aussehen: BASIC,SORT 1 REM *** SORTIER-DEMONSTRAT ION *** 10 CLEAR: TEXT 20 HOME VTAB 5: INPUT "ANZAHL DER ZU SORTIEREND EN STRINGS? ";N 30 DIM A$(N) 40 B$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ " 50 HOME VTAB 5: FLASH: PRINT "STRINGS WERDEN ERZEUGT": NORMAL 60 FOR I = 1 TO N: FOR J = 1 TO 10 70 A$(I) = A$( I) + MID$ (B $, INT ( RND (1) * 26) + 1,1 ) 80 NEXT J,I 90 HOME FOR I = 1 TO N: PRINT A$(I ) : NEXT PRINT 100 INPUT " SORTI ERBEG I NN";C$ 110 M = N: REM CA . 77 SEKUNDEN BEI N=100 120 FOR I = 1 TO M - 1 125 PRINT " . " ; 130 FOR J = I + 1 TO M 140 IF A$(I) < = A$(J) THEN 160 150 H$ = A$(I) :A$(I) = A$(J):A$(J) = H$ 160 NEXT J , I 170 PRINT INPUT " F'UER SORTIERTE LISTE";C $ 180 HO ME : VTAB 5: FOR I = 1 TO N 190 PRINT I ;: POKE 36,5: PRINT A$(I): NEXT I 200 END
Damit Sie den Verlauf besser verfolgen können , wird bei jedem Durchgang durch die äußere Schleife ein Punkt ausgegeben. Für 100 Zeichenketten mit der konstanten Länge 10 benötigt das BASIC-Programm ca . 77 Sekunden . Das fo lgende Maschinenprogramm verkürzt diese Zeit auf ca. 3,5 Sekunden. Es ist also gut 20-mal schneller. BSORT
1 2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19 20 21 22 23
;******************************* "Bubble-Sortierer " BSORT * ;******************************* ZAHL COUNT LI NKS RECHTS SUBF'LAG CMPFLG VARNAM LOWTR MF'AC SF'AC AMPER DATA MISMTCH STRCMP PTRGET BSSERR
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
$0000 $0002 $0004 $0006 $0014 $0016 $0081 $009B $009D $00A5 $03F5 $D995 $DD76 $DF'7D $DF'E3 $E1 96
ORG $0300
;+ ;+ ;+ ;+
$0001 $0003 $0005 $0007
;+ $0082 ;+ $009C
148
0300: 0302: 0305: 0307: 030A: 030C: 030F:
6. Und imm er schön variabel bleiben!
A9 8D A9 8D A9 8D 60
4C F5 03 10 F6 03 03 F7 03
0310: A9 40 0312: 85 14 0314: 20 E3 DF
0317: 0319: 031B : 031D: 031F: 0322:
0325: 0327: 0329: 032B: 032 E:
AO Bl 49 FO 20 4C
A5 45 30 20 4C
04 9B 01 06 57 03 96 EI
81 82 06 57 03 76 DD
033 1: A9 06 0333: 85 16
0335: 0337: 0338: 033A: 033C: 033 E: 0340:
A5 18 69 85 A5 69 85
9B 07 04 9C 00 05
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
0342: C8 0343 : Bl 9B 0345: 85 01
73 74 75 76 77
&- Vektor setzen LDA STA LDA STA LDA STA RTS
#$4C AMPER *<START AMPER+l *> START AMPER+2
;JMP ;Ampersand Sprung;vektor setzen
Variable suchen , nicht neu anlegen START
LDA #$40 STA SUBFLAG JSR PTRGET
;nicht neu ;einrichten ;l. Variable
Nur eindimensionale Felder LDY LDA EOR BEQ JSR JMP
#$04 (LOWTR) ,Y #$01 OKAY ENDE BSSERR
;Dimensionen ;nur 1 erlaubt ;Flagge zurück ;Bad Subscript Error
Prüfen, ob Zeichenkette OKAY
LDA EOR BMI JSR JMP
VARNAM VARNAM+l OKAYl ENDE MISMTCH
;l. Zeichen ; 2. Zeichen ;String ; Flagge zurück ;Fehlermeldung
Vergleichs flagge setzen für OKAYl
LDA #$06 STA CMPFLG
Auf Variable mit Index LDA CLC ADC STA LDA ADC STA
(
=
; (=
o
zeigen
LOWTR #$07 LINKS LOWTR+l #$00 LINKS+l
; auf l. Wert ;zeigen ;Übertrag
Feldgröße bestimmen. Wert-l ist die Anzahl der Durchläufe INY LDA (LOWTR) , Y ;Anzahl Hi STA ZAHL+l
6.5 Etwas Ordnu ng kann nicht schaden 0347 : 0348 : 034A: 034B : 0340: 034F': 0351 : 0353: 0355:
C8 BI 38 E9 85 BO C6 05 00
9B 01 00 02 01 01 07
0357: A9 00 0359: 85 14 035B : 4C 95 09
035E: 0360: 0362 : 0364:
A6 A4 84 86
01 00 02 03
0366 : A5 04 0368: A6 05
036A : 036B : 0360 : 036F': 0371 : 0372 : 0374: 0376: 0378 : 037A: 037C: 037E:
18 69 85 85 8A 69 85 85 A5 A6 85 86
03 AO 06 00 Al 07 04 05 A8 A9
0380: 20 70 DF' 0383: A5 90 0385: 00 OF'
0387: 0389: 038B: 038C: 038E: 0390: 039 1 :
AO BI AA BI 91 8A 91
02 04 06 04 06
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
NODEC
INY LDA SEC SBC STA BCS DEC ORA BNE
149 (LOWTR ) , Y
;dito Lo
*$01 ZAHL NODEC ZAHL+l ZAHL+l LOOPI
;-1
Flagge zurücksetzen , dann nächster Befehl ENDE
LDA *$00 STA SUBF'LAG JMP DATA
;ENDE ! !
Äuße re Sc hleife LOOPI
LDX LDY STY STX
ZAHL+l ZAHL COUNT COUNT+l
;Hi ;Lo
LDA LINKS LDX LINKS+l Inne re Schleife LOOP2
CLC ADC STA STA TXA ADC STA STA LDA LDX STA STX
*$03 MF'AC+3 RECHTS *$00 MF'AC+4 RECHTS+l LINKS LINKS+l SF'AC+3 SF'AC+4
JSR STRCMP LDA MF'AC BNE NOSWAP
;merken ;ev. Übertrag
;vergleichen
Variablen-Deskriptor tauschen SWAP
LDY LDA TAX LDA STA TXA STA
*$02 (LINKS), Y ;retten (RECHTS) , Y (LINKS), Y (RECHTS), Y
6. Und imm er schön variabel bleiben!
150 0393: 88 0394 : 10 F3
0396: 0398 : 039A: 039C: 039E: 03AO: 03A2: 03A4: 03A6: 03A8:
A5 DO C6 C6 A5 05 FO A5 A6 DO
02 02 03 02 02 03 06 06 07 CO
03AA: 03AC: 03AD: 03AF: 03Bl: 03B3: 03B5: 03B7: 03B9: 03BB: 03BD: 03BF: 03Cl: 03C3:
A5 18 69 85 90 E6 A5 DO C6 C6 A5 05 FO DO
04 03 04 02 05 00 02 01 00 00 01 94 99
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
DEY BPL SWAP Schleifenenden, Zähler heruntersetzen NOSWAP INNEN
AUSSEN
ENDTEST ET
LDA BNE DEC DEC LDA ORA BEQ LDA LDX BNE
COUNT INNEN COUNT+l COUNT COUNT COUNT+l AUSSEN RECHTS RECHTS+l LOOP2
LDA CLC ADC STA BCC INC LDA BNE DEC DEC LDA ORA BEQ BNE
LINKS *$03 LINKS ENDTEST LI NKS+l ZAHL ET ZAHL+l ZAHL ZAHL ZAHL+l ENDE LOOPI
;innere Schleife
; hi ; immer
;Übertrag
Das BASIC-Programm zeigt die Leistungsfähigkeit und die Syntax von BSORT.
BSORT.DEMO 1 5 10 20 30 40 50 60 70 80 90 100 110 170 180 190
REM *** SORTIER-DEMONSTRATION *** CLEAR TEXT PRINT CHR$ (4); "BRUN BSORT . OBJ" HOME VTAB 5: INPUT "ANZAHL DER ZU SORTIERENDEN STRINGS? ";N DIM A$(N) B$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" HOME: VTAB 5 : FLASH: PRINT "STRINGS WERDEN ERZEUGT": NORMAL FOR I = 1 TO N: FOR J = 1 TO 10 A$(I) = A$(I) + MID$ (B$, INT ( RND (1) * 26) + 1 , 1 ) NEXT J,I HOME FOR I = 1 TO N: PRINT A$(I): NEXT PRINT INPUT " SORTIERBEGINN "; C$ & A$(l) PRINT: INPUT " FUER SORTIERTE LISTE"; C$ HOME: VTAB 5: FOR I = 1 TO N PRINT I ; : POKE 36 , 5 : PRINT A$(I): NEXT I
6.5 Etwas Ordnung kann nicht schaden
151
Zum Aufruf und zur Parameterübergabe benutzen wir wieder den A mpe rsandVektor, der in den Zeilen 26 bi s 32 initiali siert wird. Jeder Aufruf führt da nn zu START in Zeile 36. Vo r der Suche der Va riable n mittels PTRGET wird SUBFLAG ($0014) a uf $40 (B it 6) gesetzt. Das ve rhindert, daß PTRGET die bezeichnete Variable neu a nlegt, fa lls sie noch nicht existi ert , denn wir wollen nur vorhandene Felder sortieren. Da BSORT nu r für eindime nsio nale Felder geeignet ist , wird in Zeile 40/41 die Dimensionsanzahl ge prüft und im Fehlerfall die Meldung "BAD SUBSCRIPT ERROR" ausgegebe n, nachdem zuvor noch di e SUBFLAG zurückgesetzt wurde. Da BSORT nur Zeichenketten bearbeiten kann , muß geprüft werden , ob das aufgerufene Variab lenfeld einen String bezeichnet. Dazu werde n die vo n PTRGET in V ARNAM abgelegten ersten beiden Va ri ablenzeichen miteinander EOR-ve rknüpft. Bei ein e r Zeichen kette ist Bit 7 im ersten Byte gelöscht und im zweite n Byte gesetzt. Durch Excl usiv-ODER verknüpft e rhalte n wir ein gesetztes Bit 7 , also ein negatives Ergebn is. Bei den reellen Zahlen und den Ganzzah le n sind dagegen die Bits 7 e ntweder beide gesetzt ode r beide gelöscht , sodaß die Verknüpfung immer ein gelöschtes Bit 7 und damit ein positives E rgeb nis liefert. Unser Test verläuft also ganz ei nfach und endet im Feh lerfa ll in de r Meldung "TYPE MISMATCH ERROR" . In den Zeilen 59/60 wird die Vergleichflagge CMPFLG ($0016) auf $06 gebracht , um den Vergleichstyp <= festzulegen. Wir gehen darauf noch ein. Da wir von "Links" nach " Rechts" durch unser Feld gehen wo ll en , merke n wir uns die Adresse des e rsten E le ments in LINKS und LINKS + 1. Beim BubbleSort benötigen wir bei n E lementen n-1 Durchläufe . W ir lesen des halb die Feldgröße aus dem Variablenkopf, subtrah ieren 1 und merken uns das Ergeb nis in ZAHL und ZAHL+ 1. In de n Zeil en 85 und 86 können Sie sehen , wi e man schnell eine 2-Byte-Za hl daraufhin prüfen kann , ob sie Null ist. Der Akk umulator e nth ält noch das H i-B yte . Er wird mit dem Lo-Byte ODER-verk nüpft (ORA ZAHL+ 1). Nur wenn beide Bytes $00 sind , wird die Zero-Flag gesetzt , und das Programm fä llt durch die Ve rzweigung nach ENDE durch. Ist ein Byte vo n Null verschieden, verzweigen wir in die äußere Schleife LOOP1. Zum Vergleich der Zeichen ketten woll en wir die Applesoft-Ro utine STRCMP ($DF7D) benutzen. In MFAC+3 und MFAC+4 (im fo lgende n als (MFAC) beze ichnet) mu ß dazu die Adresse des einen Stringdeskripto rs eingetragen werden. SFAC+3 und SFAC+4 (a ls (SFAC) bezeichnet) müssen auf den anderen Stringdeskriptor zeige n. Die Art des Vergleichs wird durch CMPFLG festgelegt. Dabei gilt: (SFAC) < (MFAC) => 4 (SFAC) = (MFAC) => 2 (SFAC) > (MFAC) => 1.
152
6. Und immer schön variabel bleiben!
Sie können auch zwei Gru ndoperationen verbinden: < und = ergibt 4 + 2 = 6. Genau diesen Wert haben wir deshalb vorhin nach CMPFLG geschrie ben. Ist das Ergebnis des Vergleichs "wahr", so trägt STRCMP eine 1 in MFAC ein , für "fa lsch" wird eine 0 nach MFAC geschrie ben (gen au gesagt: 8180 00000000 für 1 und 00 00 00 00 00 00 für 0). Der Anfang der inneren Schleife LOOP2 tut nichts weiter, als das linke (feste) E lement nach (SFAC) und das rechte E lement nach (MFAC) ei nzutrage n. Bei jedem Durchgang durch die innere Schleife wird (MFAC) auf das nächste E lement weitergesetzt , bis wir das Feldende erreicht haben. Ist das lin ke E lement (SFAC) < = dem rechten E lement (MFAC) , dann stimmt die Reihenfo lge schon, und wir brauchen beide E lemente nicht zu vertauschen. Bei dem E rgeb nis "wahr" muß also der Tausch übersprungen werde n. "Wahr" bedeutet eine 1 im MFAC. Wird der Exponent vo n MFAC in den Akkumulator gelade n (Zei le 120) , so führt "wa hr" zu einem Löschen des Zero-Bits im Statusregister. "Wahr" ist also identisch mit ein em "NOT EQUAL TO ZERO" . Daraus fo lgt , daß unser Verzweigungsbefeh l zum Umgehen des A ustausches "BNE" heißen muß. D ie Z eilen 125 bis 133 so llten Ihnen bekannt vo rkomme n. Es handelt sich um die Routine SW AP , die all erdings hier nur die drei Bytes des Deskriptors umsetzen muß , die bei einem Feld in der Tabelle stehen. Wenn das rechte E lement am Feldende angelangt ist , fa ll en wir in die äußere Schleife. D iese setzt das lin ke E lement um eine Position weiter und fü hrt zurück in die innere Schleife, bis auch das linke E lement das Feldende erreicht und wir mit dem Sortieren fertig si nd . Das Feldende wird allerdings dabei nicht direkt getestet. Vielmehr laufen für die innere und äußere Sch leife je ein Zähl er (ZAHL und COUNT) mit. Ist COUNT gleich Null , ist di e innere Schl eife abgelaufen, ist dagegen auch ZAHL gleich Null , so ist das ganze Programm beendet. Da sowohl ZAHL als auch COUNT 2-Byte-Zäh ler sind , ist das Herunterzählen und Testen auf Null ein klein wenig komplizierter als bei einfac hen Zählbytes.
6.5 Etwas Ordnung kann nicht schaden
153
STRCMP $DF7D Vergleicht zwei Zeichenketten miteinander. Zeiger auf 1. String in SFAC+3/4, Zeiger auf2. String in MFAC+3/4. CMPFLG ($0016) gibt die Art des Vergleichs an. Ist der Vergleich "wahr" , wird MFAC auf 1 gesetzt , andernfa lls auf O. Ei ngabe : SFAC+3/4 = Zeiger auf 1. String-Deskriptor MFAC+3/4 = Zeiger auf 2. String-Deskriptor CMPFLG (SFAC) > (MFAC) => 1 (SFAC) = (MFAC) => 2 (SFAC) > = (MFAC) => 3 (SFAC) < (MFAC) => 4 (SFAC) < > (MFAC) => 5 (SFAC) < = (MFAC) => 6 Ausgabe: MFAC = 1 (wahr), MFAC VALTYP ($0011) = 0
= 0 (falsch)
BSORT eignet sich nur für Zeichenketten. Wollen Sie Zahlen miteinander vergleichen , so bietet uns Applesoft eine weitere Routine an , die genau wie STRCMP arbeitet, aber nur Fließkomma-Zah len vergleicht , die komplett in MFAC und SFAC stehen müssen. Sie können zu diesem Transport z.B. MOVFM ($EAF9) und MOVSM ($E9E3) benutzen.
154
6. Und immer schön variabel bleiben!
COMP $DF6A Vergleicht zwei F li eßkom ma-Zah len miteinander , die im SFAC und MFAC stehen. CMPFLG ($0016) gibt die Art des Vergleichs an. Ist der Vergleich "wahr", wird MFAC auf 1 gesetzt , andernfa lls auf O. E ingabe: SFAC = 1. FP-Z ahl MFAC = 2. FP-Zahl CMPFLG ~FAC > MFAC => 1 SFAC = MFAC => 2 SFAC > = MFAC => 3 SFAC< MFAC => 4 SFAC <> MFAC => 5 SFAC <= MFAC => 6 iAusgabe: MFAC = 1 (wahr) , MFAC = 0 (fa lsch)
Wenn Sie ein uni verse lleres Sortierprogramm benötigen , finden Sie im "Peeker 1/86" eine Q uicksort-Routine vo n H. Grumser , die noch ca . 10-mal schn eller als BSORT ist. Sie hat allerd ings den Fehler , SUBFLAG nicht wieder auf $00 zu setzen , weshalb z.B . nachfo lge nde INPUT-Befeh le abstürze n. Mit Ihren jetzigen Ke nntnissen wird Ihnen die Korrektur des QUICKSORT aber ni cht mehr schwerfallen.
155
7. Kleinvieh macht auch Mist Bevor wir uns an die letzten drei großen Projekte dieses Buches machen , woll en wir die Anwe ndung unserer bisherigen Ke nntnisse mit ei n paa r praktischen Programme n übe n.
7.1 Konstant im Wandel D ie Umwand lung zwische n Zah le n mit ve rschiedener Z ahl e n basis gehört zu den alltäglichen Aufgaben eines Assembler-Progra mmi ere rs. Deshalb ist in ASSESSOR auch eine e ntspreche nde Routine eingeba ut (d ie Fragezeichen-Funktion) , die Sie ständig aufrufen kö nn en. Das Programm HEX-DEZ könn en Sie dagegen z .B. benutzen , wenn Sie BASIC-Programme schreibe n. Es wird in die unter BASIC fre ie Seite 3 geladen und mit de m A mpe rsand-Vekto r direkt a ufgerufen. Dabei be nutze n wir wieder za hlreiche ROM-Routine n, die fast die gesamte Arbeit für uns verrichten.
HEX-DEZ 1 2 3 4 5 6 7 8 9 10 11
12 '13 14 15 16 17
;********************* * HEX - DEZ CONVERT * * ;********************* ORG $300 A2L A2H LINNUM CHRGET TXTPTR DOSWRM AMPER F'RMEVL SYN ERR GETADR
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
$003 E $003F' $0050 $00B 1 $00B8 $03DO $03F'5 $DD7B $DEC9 $E752
7. Kleinvieh macht auch Mist
156
0300: 0302: 0305: 0307: 030A: 030C: 030F:
A9 8D A9 8D A9 8D 4C
4C F5 12 F6 03 F7 DO
03 03 03 03
0312: C9 44 0314: DO OE 0316: 0319: 031C: 031F: 0321:
20 20 20 A6 4C
Bl 7B 52 50 41
00 DD E7 F9
0324 : C9 48 0326: FO 03 0328: 4C C9 DE 032B: 032D: 032F: 0330: 0332 : 0334: 0337: 0339: 033C: 033E: 0340:
A2 A4 C8 09 81 20 DO 20 A5 A6 4C
00 B8 80 B8 Bl 00 F7 A7 FF 3F 3E 24 ED
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
LINPRT PRNTAX GETNUM
EQU $ED24 EQU $F941 EQU $FFA7 LDA STA LDA STA LDA STA JMP
U 4C AMPER *< START AMPER+l *) START AMPER+2 DOSWRM
START
CMP * 'D' BNE NODEZ Dezimal nach Hexadezimal JSR CHRGET ; l. Ziffer lesen JSR FRMEVL ;Ausdruck - ) FAC ;FAC - ) LINNUM,A-Y JSR GETADR LDX LI NNUM ;Lo JMP PRNTAX ;hex. ausgeben
NODEZ
HEXDEZ MASKE
CMP * 'H' BEQ HEXDEZ JMP SYNERR LDX LDY INY ORA STA JSR BNE JSR LDA LDX JMP
; ungül tig
; init. ; merken und ; auf l. Ziffer zeigen U80 ;Bit7 setze n (TXTPTR,X) ;X = 0 ! CHRGET ; nächstes Zeichen ; 0 = Ende MASKE ; ASCII - ) HEX GETNUM A2H ;Hi A2L ;Lo LINPRT ;dez . ausgeben *00 TXTPTR
Der Ampersand-Vektor wird in der uns schon bekannten Art auf START gesetzt. Wenn wir das Programm aufrufen wollen , geben wir ein & ein , gefolgt von "D" für eine Dezimalzahl oder "H " für eine HEX-Zahl. Danach steht die Zahl selber. Ihr Wertebereich umfaßt 0 bis 65535 ($0000 - $FFFF). Beim Auftreten des &-Zeichens springt der BASIC-Interpreter über $03F5 nach START, wobei sich das Zeichen nach dem & (hier also D oder H) im Akkumulator befindet. Wenn es ein "D" ist , gelangen die Zeilen 32 bis 37 zur Ausführung. JSR CHRGET stellt den TXTPTR auf das folgende Zeichen und holt es in den Akkumulator. Dies ist die Vorbedingung für die Routine FRMEVL ($DD7B) , die einen beliebigen Ausdruck an der TXTPTR-Stelle auswertet und nach MFAC schreibt. FRMEVL gehört zu den mächtigsten Teilen von Applesoft und verarbeitet auch beliebige Kombinationen aus Konstanten und Variablen. 25*A-1O wäre also z.B. erlaubt. Ist der Ausdruck
7.1 Konstant im Wandel
157
numerisch, steht in MFAC die ungepackte Fließkomma-Zahl. Ist der Ausdruck eine Zeichenkette, steht ein Zeiger auf den Deskriptor im dritten und vierten Byte des MFAC. GETADR ($E752) wandelt den MFAC in eine Ganzzahl in LINNUM ($0050/51) bzw. im Y-Register und im Akkumul ator um. PRNTAX ($F941) gibt schließlich diese Ganzzahl hexadezimal über COUT aus. Dazu muß das Hi-Byte im Akku und das Lo-Byte im X-Register stehen. Das X-Register wird aus LINNUM geladen , der Akku ist bereits korrekt gesetzt.
FRMEVL $DD7B Wertet beliebigen Ausdruck eines Typs aus. Eingabe: TXTPTR zeigt auf 1. Zeichen des Ausdrucks Ausgabe: TXTPTR zeigt hinter den A usdruck a) Ausdruck ist numerisch MFAC = Fließkomma-Zahl des Ausdrucks VALTYP ($0011) = $00 b) Ausdruck ist Zeichen kette MFAC+3/4 ($00AO/A1) e nthält Zeiger auf den Deskriptor VALTYP ($0011) = $FF
GETADR $E752 MFAC «65536) wird in 4-stellige Hexzahl ohne Vorzeichen in LINNUM umgewandelt. Eingabe: MFAC enthält Fließkomma-Zahl Ausgabe: LINNUM ($0050/51) = Ganzzahl-Anteil von MFAC Akku = Hi-Byte, Y-Reg = Lo-Byte
158
7. Kleinvieh macht auch Mist
PRNTAX $F941 Akkumul ator und X-Register werden als HEX-Zah l über COUT ausgegeben. E ingabe: Akku = Hi-Byte der Zahl X-Reg = Lo-Byte der Zahl A usgabe: Akku verändert
PRNTYX $F940 Y- und X-Register werden als HEX-Zah l über COUT ausgegeben. Eingabe: Y-Reg = H i-Byte der Zah l X-Reg = Lo-Byte der Zahl A usgabe: Akku verändert
War der Ken nbuchstabe ein "H ", werden die Zei len 43 bis 53 ausgeführt. In jedem anderen Fa ll wird "SYNTAX ERROR" ausgegeben.
SYNTERR $DEC9 Gibt "SYNTAX ERROR" aus E in gabe: Ausgabe: Fehlermeldung über COUT. Macht BASIC-Warmstart oder springt in eine ONERR-Behandlung.
Da wir unser Programm aus einer BASIC-Umgebu ng aufrufen , wird unsere E ingabezeile von Applesoft bearbeitet, d.h . sie wird bei einer Direkteingabe mit gelöschtem Bit 7 im Tastaturpuffer abgelegt. Die Zei len 43 bis 49 setzen wieder
7.2 E in Spürhund für Ad ressen
159
Bit 7, bis sie auf ein Zeil enende ($00) oder ein Befehlsende (: = $22) stoßen. GETNUM ($FFA 7) wa ndelt die ASCII-kodierte E ingabe in eine 2-Byte H EXZ ahl in A2L1H ($003E/3F) um . LINPRT ($ED24) schließlich gibt den Inh alt vo n Akk umulator (Hi) und X-Register (Lo-Byte) über COUT als Dezimalzahl aus.
GETNUM $FFA7 Wa ndelt eine 2 bis 4-stellige HEX-Za hl enke tte (ASCII-kodiert mit Bit 7 gesetzt) in eine 1-2 Byte HEX-Zahl in A2L und A2H. E inga be: Zeichen kette im Tastaturpuffer ab $0200 , B it 7 gesetzt Y-Reg = Position im Puffer (normal auf $00 setzen) A usgabe: A2L1H ($003E/3F) e nth ält HEX-Zahl (Lo/H i) .
LINPRT $ED24 G ibt 4-stellige HEX-Za hl dezim al über COUT aus . E inga be: X-R eg = H i-Byte, Akk u
= Lo-Byte
A usgabe : -
7.2 Ein Spürhund für Adressen E ine der sinnvo llsten A rten , die Asse mbler-Programm ierung zu e rlernen, ist das Di sassembli eren und Ve rstehen vo n fremden Programm en. D abei kann es sich um die eingebauten ROMs handeln oder um belie bige ladbare Maschinenprogramme , di e irgendetwas für Sie Interessantes tun . Der zu nächst schwierigste Teil bei diesem "Schnuppern " in fre mde n Geda nke ngängen ist es, einen Überblick über die verschi edenen T eile ein es Gesamt programms zu erhalten. In
160
7. Kleinvieh macht auch Mist
der R egel macht man sich da ran, kleine Teile , die leicht verstä ndlich sind , zu disassemblieren und zu ko mme ntieren . We nn Sie so eine n kleinen Teil verstande n habe n , ist es sicher interessan t zu wisse n, welche übrigen Tei le des Gesamtprogramms die von Ihnen verstande ne U nterrouti ne benutzen. Sie müssen dazu das gesamte Progra mm nach A ufrufe n für dieses U nterprogra mm durchsuchen . Da dies eine sehr zeitaufwä ndige Tätigkeit sein ka nn , schreiben wir uns für eine auto matische Suche ein kleines Program m. D ieses durchkämmt wie ei n Spürhund einen vo n Ihne n angegebenen Speicherbereich und listet Ihne n all e Zeilen , di e einen A ufruf der vo n Ihnen spezifizierte n Ad resse e nthalte n.
CROSSREFERENZ 1 2 3 4 5 6 7 8 9 10 11
0300: 0303 : 0304 : 0306: 0309: 030C: 030 E: 03 11 :
AD 18 69 8D AD 69 8D 4C
72
14 F9 73 00 FA 69
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 AA 35 36 37 03 38 AA 39 40 03 41 FF 42
;******************************* Cross referenz für Adressen * * (C) 1985 Dr. Jürgen Kehrel * ;******************************* Start mit BRUN unter DOS 3.3 Holt seine Ladeadresse aus dem DOS und initia l isiert CTRL-Y
* Adresse
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
$002F $003A $003B $003C $003D $0042 $0043 $03F8 $AA72 $COOO $C010 $F88C $F8DO $F956 $FCBA $FD8E $FF69
ORG $300 INIT
LDA CLC ADC STA LDA ADC STA JMP
BLOADADR *START-INIT USRADR+l BLOADADR+l 11$00 USRADR+2 MONZ
;DOS 3.3
7.2 Ein Spürhu nd für Adressen
0314: 0316 : 0318: 031A: 031C: 031D: 031F: 0321 :
AO BI C5 DO C8 BI C5 DO
00 3C 42 lE 3C 43 17
0323: 0325 : 0327 : 0329: 032A : 032B : 032D: 032F: 0331 : 0334: 0336: 0338:
A6 M DO CA 88 86 84 A2 20 A5 C9 FO
3B 3A 00 8C F8 2F 02 26
033A: 033C: 033E : 0340 : 0342 :
AO BI 29 C9 DO
00 3C IF 10 2F
0344: 0346 : 0348: 034A: 034C: 034E : 0350 : 0353: 0354 : 0355 : 0357: 0358 : 035A : 035C: 035E:
M
A6 84 86 AO BI 20 AA E8 DO C8 E4 DO C4 DO
3D 3C 01
3C 3D 3A 3B 01 3C 56 F9 01 42 17 43 13
0360 : 20 DO F8
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
START
LDY LDA CMP BNE INY LDA CMP BNE
UOO (AIL),Y ML RELATIV
;mit Lo-Byte vergI. ;nächstes Byte
(AlL), Y MH RELATIV
;mit Hi-Byte vergI. ;nicht gefunden
Überprüfe, ob 3-Byte Befehl
NODEC
RELATIV
72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
161
LDX LDY BNE DEX DEY STX STY LDX JSR LDA CMP BEQ
AIH AlL NODEC
LDY LDA AND CMP BNE
#$00 (AIL),Y UIF U IO WEITER
PCH PCL U OO INSDS2 LENGTH U02 FUND
;Adresse - 1 ;zei gt auf Opcode ;kein Übertrag
; init. ;3-Byte Befehl ;OK. anzeigen ;Byte erneut ;Trick vom alten ; Monitor für Branch
Setze Offset zur Adresse um
NOINC
LDY LDX STY STX LDY LDA JSR TAX INX BNE INY CPX BNE CPY BNE
AlL AIH PCL PCH UOl (AI L),Y PCADJ3 NOINC ML WEITER MH WEITER
;Offsetbyte lesen ;und mit Monitor ;die Adresse-l in ;A (Lo) und Y (Hi) ;berechnen, dann ;korrigieren ;vergleichen ;nicht gefunden
Gefundene Stelle disassemblieren FUND
JSR INSTDSP
;PCL/PCH OK.
Pause/Weiter bei Tastendruck
162 0363: 0366: 0368: 036B: 036E: 0370:
0373: 0376: 0378: 037A: 037C: 037E: 0380: 0382:
7. Kleinvieh macht auch Mist
2C 10 2C 2C 10 2C
20 BO A5 C9 DO A9 85 DO
00 OB 10 00 FB 10
CO CO CO CO
BA FC OC 3D CO 96 DO 3D 90
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
PAUSE
BIT BPL BIT BIT BPL BIT
KBD WEITER STROB E KBD PAUSE STROBE
;kein Tastendruck ; l öschen ;neuer Tastendruck ? ;Nein ;J a , l öschen u. weiter
Nächste Adresse , aber $COOO-$CFFF aus l assen WEITER
J SR BCS LDA CMP BNE LDA STA BNE
NXTAI SCHLUSS AIH 1F$CO START 1F$DO AIH START
;we itersetzen ; 1/0 meiden ;bei $DOOO weiter ;immer
115
0384: 4C 8E FD
116
SCHLUSS
JMP CROUT
; ausgeben, Ende
Wir wollen dieses Programm aus dem Monitor hera us aufr ufen (also nach CALL-1 51) . Zum Befehlsaufruf und zur Parameterübergabe benutzen wir den Control-Y-Vektor. Er zeigt gewisse Ä hnli chkeiten zu m A mpersand mit dem U nterschied , daß er nur im Mo nitor (und nicht vo n A pplesoft aus) benutzt werden kann , und daß er nach $03F8 springt. Außerdem werden alle Zeichen vor entsprechend ei nem bestimmten Schema ausgewertet und in Zero-Page (Null-Seiten) Speicherstellen geschrieben. U nser Programm hat noch eine weitere E igenschaft: es ist relokati v. Dies hei ßt , daß es an jeder RAM-Adresse ablauffähig ist. Die meisten Maschinenprogramme können nur ab der Ad resse ausgefüh rt werden , die durch den ORG-Befeh l festgelegt wurde. Sie sind nicht versc hiebbar (nicht relokativ). Dies liegt daran , daß sie Befehle enth alten, die feste Ad ressen innerhalb des Codes benutzen. Besonders betroffen davo n sind JMPs und JSRs sowie alle Lade- und Speicherbefeh le (LD. und ST.) , die Adressen innerhalb des Programms betreffe n. Wenn sich das Programm nämlich nicht an der durch ORG festgelegten Ad resse befindet , stimmen diese Adresse n nicht mehr und die Befeh le "greifen ins Leere" , was in der Regel einen Absturz verursacht. Referenzen auf a bsolute A dressen außerhalb des Programms (z.B. im ROM) sind dagegen kein H in dernis für eine Ve rschiebung, da di ese Ad ressen imm er konstant bleibe n, auch wenn das Programm im Speicher verschoben wird. E in ,,JSR COUT" ist von überall her ausführbar. Wenn Sie bei einem Programm schnell einmal sehen mü ssen , ob es relokativ ist , brauchen Sie sich im Assembler-Listing nur die Befehle anzusehen, di e 3 Bytes Objektcode erzeugen. Hiervon ist normale rweise nur das H i-Byte des O peran-
7 .2 Ein Spürhund für Adressen
163
den interessant. Es steht ganz rechts. Wenn wir durch unser Programm "Crossreferenz" schauen , finden wir die Bytes AA, 03 , AA, 03 , FF, F8 , F9 , F8, CO , CO , CO, CO, FC und FD. Mit Ausnahme der beiden ,,03" bezeichnen sie Hi-Bytes , die außerhalb des Programms liegen. Sie sind einer Verschiebbarkeit also nicht abträglich. Bei den beiden ,,03" müssen wir un s jetzt noch die Lo-Bytes ansehen: wir finden F9 und FA. Auch sie liegen außerhalb des eigentlichen Programms. Daraus folgt, daß unser Programm keine absolute Adressen in sich selber benutzt , also beliebig im Speicher verschiebbar ist. Noch eine kleine Anmerkung: jeder JMP zu einem Ziel innerha lb des Programms bindet dieses an seinen Ausführungsort. Wenn das Sprungziel nicht weit entfernt ist , eignet sich deshalb ein "Branch" besser , der relativ adressiert und immer relokativ ist. Besitzer des 65C02 haben es da ei nfach: "BRA" verzweigt immer zu der angegebenen Adresse. Wenn Sie nur einen 6502 haben , können Sie zunächst eine Statusflagge definiert setzen und diese dann mit einem Branch-Befehl "testen". Besonders beliebt ist die Befehlsfolge
CLV BVC xxxx , da das Löschen des Overflow-Bits normalerweise in ein em Programm keinen Schaden anrichtet. Durch diese beiden Befeh le erreichen Sie auch eine unbedingte Verzweigung. Was ist zu tun, wenn das Sprungziel zu weit für einen Branch-Befehl entfernt liegt? Ganz einfach , Sie bauen "Zwischenlandungen" ein , so wie ein Dreispringer auch den Boden zwei mal zwischendurch berühren darf. Tei len Sie den gesamten Abstand in mehrere Teilsprünge auf. Da die getestete Flagge sich zwischenzeitlich nicht verändert , reicht es , nur den Branch-Befeh l zu wiederholen:
CLV BVC EINS
unbedingte Verzweigung
EINS BVC ZWEI
1. Zwischenlandung
ZWEI BVC ZIEL
2. Zwi s chenlandung
ZIEL XXX yyyy
eigentliches Ziel
Unser Programm "Crossreferenz" muß relokativ sein , um jeden erdenklichen Speicherbereich testen zu können. Wäre das Programm an seine ORG-Adresse
164
7. Kleinvieh macht auch Mist
gebunden, könnten z.B. nie Crossreferen zen (Querverweise) für den Bereich $0300 bis $0386 erste llt werden, es sei denn , Sie wollten vo n "Crossreferenz" selber eine Crossreferenz machen. Die Verschiebbarkeit bringt ein Problem für uns mit: we nn das Progamm über den Co ntrol-Y -Vektor gestartet werden so ll , muß in den Vektor die tatsächliche Start adresse eingetrage n werde n. Diese liegt vor dem Lauf des Programms aber nicht fest . Deshalb muß das Programm selber feststellen, wo es sich im Speicher befin det. Dazu wurden verschiedene Techniken entwicke lt. Wir gehen hier davon aus, daß das Programm vo n DOS 3.3 an sein e Laufadresse gelade n wurde . A uf einem Rechner mit mindestens 48K Hauptspeicher find en wir dann in den Speicherstellen $AA 72 und $AA 73 die Ad resse des letzten "BLOAD" oder "BRUN". Wir nutzen di ese Werte , um sie in den Vektor einzutrage n. Da diese bei DOS gefunde ne Ladeadresse die Ad resse des ersten Bytes (a lso von INIT) ist , wir aber das eigentliche Programm bei START starten wo llen, zählen wir noch die Länge des INIT-Tei ls dazu (Zeile 37) . Dieses Verfahren klappt nur , wenn Sie das Programm auch an der Ladeadresse laufen lasse n. Wenn Sie es dagegen mit "BLOAD" laden , in den Monitor gehen, es verschieben und dann starten, sti mmt die Adresse im DOS nicht. Der Initialisierungsteil schließt mit einem Sprung nach MONZ ($FF69). Dies ist die E insprungadresse in den Monitor , der Ihnen danach sein Sternchen-Prompt * präsenti ert. Die Syntax vo n " Crossreferenz" ähnelt der B lockversch iebu ng des Mo nitors. Zuerst nennen Sie die gesuchte Ad resse in hexadezim aler Form , abe r ohne Dollarzeichen. Di ese darf nicht auf der Zero-Page (Null-Seite) liege n. Es folgt ein "Kleiner-als"-Zeichen. Daran schließt sich die Adresse des Such beginns an , der nach einem Punkt die Adresse des Suchendes fol gt. Im Anschluß daran drücken Sie Control-Y (was auf dem Bildschirm ni cht zu sehen ist) und die RETURN-Taste: Adresse < VON .BIS(Ctrl-Y)(CR). "Crossreferenz" disassembliert Ihn en dann alle Zeilen , die di e gesuchte Adresse aufrufen. Das funktioniert auch bei Branch-Befehlen , da hier die relative Adresse in die absolut aufger ufe ne umgerech net wird. Bevor wir uns das Listing näh er ansehen , müssen wir noch wissen, was der Monitor mit unseren Ei ngabe n vor dem < Ctrl-Y> macht. Die erste HEX-Zahl (Adresse) wird nach A4L und A4H ($0042/43) gespeichert . Die Ad resse nach dem < -Zeichen (VON) landet in AlL und A1H ($003C/3D) , während die
7.2 Ein Spürhund für Adressen
165
Adresse nach dem Punkt (BIS) sich in A2L und A2H ($003E/3F) wiederfin clyt. In den Zei le n 44 bis 50 wird verglichen, ob sich bei der Adresse , auf die A I LIH zeigt , die Bytefolge der gesuchten Adresse befindet. Ist das nicht der Fall , wird in Zei le 51 verzweigt, um auch relative Adressierungen zu erkennen. Wurde die gesuchte Bytefolge gefunden , muß überprüft werden , ob es sich dabei auch wirklich um eine n Opera nden handelt. Es könnte ja auch sonst durch Z ufall einmal diese Bytekombination entstehen. Es kommen nur Befehle in Frage , die 3 Bytes lang sind . Deshalb wird das Opcode untersucht , das sich vor der gefunde nen Bytekombination befindet . Die augenbli cklich verglichene Ad resse wird in die Indexregister gelade n und , um 1 vermindert , nach PCL und PCH ($003B/3C) gespe ichert. Sodann wird die Monitorrouti ne INSDS2 ($F88C) aufgerufe n , die unter anderem die Befehlslänge bestimmt. Diese wird immer um 1 kleiner angegeben. E ine 2 in der Speicherstell e LENGTH ($002F) bedeutet also einen 3-Byte-Befe hl. Wenn dies zutrifft , haben wir eine Referenz gefunde n und geben sie in Ze il e 94 mit der Monitorroutine INSTDSP ($F8DO) disassemb li e rt a us. Wa r der Befehl nicht 3 Bytes lang, testen wir auf ein en Branch-Befehl. Die Zeilen 68 bis 71 fischen alle Branch-Opcocles (bis auf BRA!!) heraus. War der Befehl auch kein B ranch , gehe n wir zur nächste n Speiche rstell e weiter (WEITER). Bei ein e m B ra nch wird durch die Mo nitorroutine PCADJ3 ($F956) die tatsächliche Adresse berechnet und mit der gesuchten verglichen . Nach jeder gefundenen Referenz können wir mit einem beliebigen T astendruck das Programm an halten und es mit einem erneuten Tastendruck wieder sta rte n. Die Zeilen 98 bis 103 erledigen dies für uns. Für das Weitersetzen der Ad resse bedienen wir uns ein e r Monitor-Routine. NXTAI ($FCBA) erhöht AILIH um 1 und testet dann, ob die Ad resse in A2L1H schon erreicht oder überschritten wurde. Liegt AIL1H noch unterhalb von A2L1H, so ist das Carry-B it gelöscht, andernfalls gesetzt. Da A2L1H unsere E ndadresse e nthält , zeigt uns ein gesetztes Carry-Bit das E nde der Suche an. Noch eine kle in e Besonderheit des Apple ist zu berücksichtigen. Der Speicherbereich von $COOO bis $CFFF enthält Softswitches oder Daten von Steckkarten. Es wäre gefährlich bzw. irreführe nd , diesen Bereich zu durchsuchen. Nach der Adresse $BFFF wird desh alb AILIH nicht auf $COOO , sondern gleich auf $DOOO weitergesetzt.
166
7. Kleinvieh macht auch Mist
INSDS2 $F88C Berechnet Länge , Format und Mnemonic-Index für das Opcode, auf das (PCL) zeigt. Eingabe: X-Reg = $00 PCLlH ($003A/3B) zeigt auf Opcode Ausgabe: FORMAT ($002E) = Adressierungsart in codierter Form LENGTH ($002F) = Befehlslänge - 1 Akk u = Index in der Mnemonic-Tabelle des Monitors
PCADJ3 $F956 Berechnet aus dem Distanzbyte die tatsächlich angesprochene Adresse bei relativer Adressierung. Eingabe: Akku = Distanzbyte PCLlH zeigt auf Distanzbyte Ausgabe: Akku = La-Byte der Adresse Y-Reg = Hi-B yte der Adresse
INSTDSP $F8DO Disassembliert einen Maschinenbefehl durch Ausgabe über COUT. Eingabe: PCLlH zeigt auf das Opcode (Befehlsbyte) Ausgabe: LENGTH ($002F) = Befehlslänge - 1 Disassembliert wie L-Befehl des Monitors , aber nur 1 Zeile
7.2 Ein Spürhund für Adressen
167
NXTAl$FCBA Setzt A1L/H um 1 weiter LInd vergleicht mit A2L/H. Eingabe: A1L/H ($003C/3D) = zu erhöhender Wert (Lo/Hi) A2L/H ($003E/3F) = Vergleichswert
Ausgabe: A1L/H um 1 erhöht Carry-Bit gesetzt, wenn A1L/H >= A2L/H
Nach einer nur kleinen Änderung ist das Programm unabhängig vom benutzten DOS und deshalb z.B. auch unter ProDOS einsetzbar. Wir finden die aktuelle Adresse durch einen kleinen Trick. Wenn wir ein JSR zu einem bekannten RTS durchführen - z.B. $FF58 im ROM - , dann könnnen wir auf dem Stack die Rücksprungadresse finden. Diese ist um genau 2 größer als die Adresse des JSR. Fügen Sie deshalb im Vereinbarungsteil folgende Zeilen hinzu:
STACK EQU $0100 IORTS EQU $FF58 ; festes RTS Den INIT-Teil schreiben Sie wie folgt um:
INIT
MONITOR
JSR TSX LDA STA DEX LDA CLC ADC STA BCC INC JMP
IORTS STACK,X USRADR+2
;auf RTS im ROM ;Stackpointer ; Hi-Byte
STACK , X ; Lo-Byte tSTART-INIT-2 USRADR+1 MONITOR Übertrag? USRADR+2 Ja MONZ zum Monitor
168
8. Speicher-Recycling
Overlay
Nachde m Sie sich im Ka pitel 6 so sehr mit Vari able n quälen mußten , so ll jetzt als Belo hnung eine pra ktische A nwe ndung folgen , di e di e Möglichke iten vo n A ppl esoft ganz beträchtlich erweitert, besonders we nn Sie gleichzeitig hochauflösende G rafi kse ite n be nu tze n wollen. A us historische n G ründe n liegen beim A pple die beide n HGR-Seite n mitten im heutigen A rbeitsspeicher. Bei kleine n A pplesoft-Programme n fällt das nicht we iter auf. We nn Ihre Programme abe r größe r werde n, passiert es leicht , daß das BASIC-Programm bi s in den Bildspeicher reicht , de nn der Pl atz vo n $0801 (dem no rmale n Start aller Applesoft-Programme) bis $2000 (dem Beginn vo n H G R Seite 1) ist nicht gerade sehr groß. Es gibt nun ve rschi ede ne Mögli chkeiten , aus di esem D il emma heraus zu kommen . E ine li egt da rin , mit de m BASIC-Programm erst o berhalb de r G rafik ($6001) anzufa ngen , wo mit DOS 3.3 immerh in Platz bis $9600 ist. E ine etwas exotische Möglichke it wurde vor Jahren in CALL A.P .P.L.E. vo rgestellt: das BASIC-Programm wird gesp littet und um die Grafik he rum aufge baut. Diese Lösung ist abe r mühsam und unflexibel. D er einfac hste Weg ist es, das Programm in mehrere Teile zu gliedern und diese dann nachein ande r auszuführe n , z .B. übe r ein EXEC-Programm ode r durch di rekten A ufruf am E nde des Vo rgänger-Progra mms ("RUN XY Z .TEILn") . Diese Lösung hat de n Nachteil , daß alle Variablen ve rlore n gehe n und zwischen de n Modulen nur schwer Info rm atio ne n überge ben werden kö nn en . E ine n Schritt besser ist die Ve rwendung des CHAIN-Programms vo n de r DOS 3.3 SYST EM MASTER-D iskette . H ier bl eibe n die Va riable n erh alte n. A ber auch CHAIN kann immer nu r ein Modul ganz durch das nächste e rsetzen . Ich habe nun CHAIN a nalysie rt und beträchtlich erwe ite rt. Daraus e ntstand de r "Applesoft-Overla y-Manager". Was kann dieses Programm nun ? Meine Überlegungen gingen dahin , da ß bestimmte Programmteile viel benötigt we rde n , andere jedoch nur selte n , z.B. we nn sortiert oder gedruckt we rden muß. Es sollte also möglich sein , ein "G rundm odul " zu lade n, das immer im Speicher
8. Speicher-Recycling = Overlay
169
verbl eibt. Dieses " G run d modul " läd sei nerseits weitere Programmteile bei Bedarf nach . Es kann sich dabei a uch se lber teilweise überschreibe n . Es können beliebig viele "Zusatzmodule" nachgelade n we rden , wobei sie sich überlage rn oder ergän zen können. Aus diesem Gru nde kann die Zei le nnumm e r angegeben werden, ab de r das neue Modul eingelade n wird . Daß sämtliche Variable n erhalte n bleiben, ist selbstverstä ndlich. Zwei kleine Einschränk ungen will ich Ihnen nicht verschweigen: We nn in dem Bereich, de r durch das neue Mod ul überschri eben wird (Overl ay-Bereich), ein DEF FN li egt, wird diese Definition ni cht gerettet. Sie kann also später nicht benutzt werde n. Vers uche n Sie es trotzdem , stürzt das Program m ab (auch CHAIN rettet Funkti onen nicht) . Der Grund ist ei nfach: Applesoft speichert bei ein er F unkti o nsdefiniti on deren absolute Lage im Speicher und holt sich bei der Benutzung der Funktion jedesmal die Definition neu a us de m BASIC-Programm. Den Ze iger umzusetzen wäre nicht schwer. Die Frage aber bleibt: wo lasse ich die Definition , die ja an ei nen a nderen Speiche rpl atz gerettet werde n müß te. Da es hierauf keine immer gültige Antwort gibt , wurde ganz dara uf verzichtet , Fun ktionen zu behandeln. Funktionsdefin itionen im nicht überschriebene n Teil des G rundmoduls funktionieren natü rlich. Das zweite Problem ist ähnlich . Im Overlay-Bereich sollte kein ONERR vorko mme n. H ierbei speichert App lesoft auf der Zero-Page sowo hl die Adresse des gü ltigen ONERR als auch seine Zei lennummer ab. Findet der Overlay-Manager ein ONERR im Overl ay-Bereich , wird dieses deaktiviert , inde m die e ntspreche nde Flagge ($00D8) zur ückgesetzt wird. Damit sind die meisten Prob le me behoben. Wen n Sie allerdings im Gru ndm odu l ein ONERR haben , das auf eine Zeile im Overlay zeigt , dann ist die Zieladresse eventuell gar nicht me hr da. Die Fo lge können Sie sich ausma le n. Sie können den "Applesoft-Ove rl ay-Manager" a n jeder Stelle ihres BASICProgramms aufrufe n , wenn Sie ihn gleich zu Beginn - noch bevor irgendwelche Varia blen definiert wurde n - initialisiert habe n . Dazu genügt es, ihn mit "BRUN" oder "BLOAD" mit anschließendem "CALL 37632" zu starte n , wodurch HIMEM: und de r Zeiger auf das E nde des Strin gpools (FRETOP) unte r das Programm gelegt sowie der A mpersand-Vektor gesetzt werden. Der "Applesoft-Overlay-Manager" ist nur für DOS 3.3 gedacht und nicht für ProDOS, das einen eigenen CHAIN-Befehl besitzt . Der Aufruf erfolgt mit dem Ampersand-Zeichen &, gefo lgt von OVL, ein em Komma, der Sta rtzeile, ab der das ne ue Mod ul eingeladen we rde n soll , ei ne m weite ren Komma und schli eß lich dem in A nführungszeichen gesetzte n Namen
170
8. Speicher-Recycling = Overl ay
des aufgerufe nen Moduls. Wenn Sie den Programm teil " ABC.TEIL3" ab Zeile 750 laden wollen, lautet der Befehl: &OVL,750 , "ABC.TEIL3" . Wichtig ist, daß die Zeilennummern in dem Overlay-Modul mindestens so groß sind wie die im Aufruf angegebene Startzeile. Höhere Zeilennummern schaden nicht , niedrigere können dazu führen , daß eine Nummer zweimal vorkommt. Dann funktionieren Sprünge nicht mehr richtig, da Applesoft nur die zuerst stehende vo n zwei Zeilen mit gleicher Nummer findet , wenn sie mit GOTO oder GOSUB angesprungen wird. Bevor wir uns mit der Programm ieru ng auseinandersetzen , folgt jetzt einm al das komplette Programm und anschließend ein e kleine Demonstration.
( OVfRLAY )
8. Speicher-Recycling = Overl ay
Abb . 10: Vereinfachter A blaufp lan des Applesoft-Overl ay-Manage rs
171
172
8. Speicher-Recycling = Overlay
OVL-MANAGER 1
2 3
4 5 6 7 8 9
:******************************* Applesoft-Overlay-Manager * (C) 1985 Dr. Jür gen Kehrel * :******************************* Version 1.3
J an. 86
Benutzt Teil e von: CHAIN Quel l e: Randy Wiggington Call A.P.P.L.E. Vol. 2 Nr. 1
10 11
12 13 14 15 16 17 18 19 20 21
Syntax : &OVL, , z . B. &OVL, 500, "MODUL1" Muß initialisiert werden, bevor St ri ngvar i ab l en angelegt werden! Nu r für DOS 3.3 !!! Im Overlay-Bereich darf sich kein DEF FN befinden . Ein ak tiv es ONERR wird wieder zurückgesetzt.
22
23 24 25 26 27 28 29 30 31 32 33
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
AlL A2L CURBUF
EQU EQU EQU A4L EQU NXTBUF EQU INDEX EQU TXTTAB EQU VARTAB EQU ARYTAB EQU STREND EQU FRETOP EQU HIMEM EQU DATPTR EQU DSCLEN EQU HIGHDS EQU HIGHTR EQU LOWTR EQU DSCTMP EQU FACMO EQU PRGEND EQU CHRGOT EQU ERRFLG EQU TEMP EQU TEMP2 EQU LOMEMFLG EQU ERRADR EQU FMGR CONNECT AMPER
$003C $00 3E $0040 $0042 $0044 $00 5E $0 067 $0069 $00 6B $0 060 $006F $0073 $0070 $008F $0094 $0096 $009B $0 090 $OOAO $OOAF $00B7 $00 08 $OO EB $OO ED $OOEF $OO F4
EQU $0306 EQU $03 EA EQU $03F5
8. Speicher-Recycling = Overlay
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
9300: 930 1: 9303: 9305: 9307: 9309: 930B: 9300 : 930F': 9312: 9314 9316 9319 931C
08 A9 AO 85 85 84 84 A9 80 A9 AO 80 8C 60
00 93 73 6F' 74 70 4C F'5 03 10 93 F'6 03 F'7 03
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
CLRF'NBUF' ZEROPRMS F'ILEREAO R02BYTE NOBUF'S TOLARGE OOSERR CMPLPRMS COPYF'N COPYBP GETBUF' F'NBUF'1 F'MPL BLTU2 F'NOLIN STKINI NEWSTT RESTORE LINGET CHKSTR F'RMEVL CHKCOM SYNCHR SYNERR GARBAG F'RESTR MOVE SETKBO SETVID
173
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
$A095 $AIAE $A471 $A47A $A6C8 $A6CC $A602 $A7 1A $A743 $A74E $A764 $AA75 $B5BB $039A $061A $0683 $0702 $0849 $OAOC $006C $007B $OEBE $OECO $OEC9 $E484 $E5F'0 $F'E2C $F'E89 $F'E93
ORG $9300
;bei MAXF'ILES 3
Legt HIMEM unter das Maschinenprogramm und setzt den &-Vektor START
CLO LOA LOY STA STA STY STY LDA STA LOA LOY STA STY RTS
* <START *>START HIMEM F'RETOP HIMEM+l F'RETOP+l U4C AMPER *< OVERLAY *> OVERLAY AMPER+l AMPER+2
;JMP
Hauptprogramm Packt Strings unter HIMEM
174
8. Speicher-Recycling = Overlay
9310: 20 84 E4 9320: 20 B7 00
110
OVERLAY
111
JSR GARBAG J SR CHRGOT
112 113 114
9323: 9325: 9328: 932B: 932C:
A2 BO 20 CA 10
03 A7 95 CO OE
9341: 9343: 9345: 9347: 9349: 934B:
9340: 934F: 9351: 9353: 9355: 9357: 9359: 935B:
A5 A6 80 8E
A5 C5 90 A5 C5 66
24 10 A5 C5 A5 E5 90 46
OVI
117
118 F7
932E: 20 OC OA 9331: 20 BE OE 9334: 20 1A 06
9337: 9339 : 933B: 933E:
115 116
Befehlsaufruf "OVL," testen
9C 9B A6 95 A5 95
BO 6A 04 AF 69 EF
08 OC F4 9B F5 9C 02 08
119
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
LOX LOA JSR OEX BPL
t$03 AUFRUF,X SYNCHR
;testen
OV1
Zeilennummer holen und auf das zugehörige Link-Feld zeigen JSR LINGET JSR CHKCOM JSR FNOLIN
;folgt Komma?
Rette Adresse LOA LOX STA STX
LOWTR+l LOWTR OVSTART+l OVSTART
Prüfen, ob LOMEM am End e des Pro gramms liegt. Wenn LOMEM im Pr ogramm gesetzt wurde, ist eine Flagge zu setzen.
SAVLOMEM
LOA CMP BLT LOA CMP ROR
PRGENO+l VARTAB+l SAVLOMEM PRGENO VARTAB LOMEMFLG
;Hi-Byte ;C = 0 {PRGENO ( LOMEM) ;Lo ;C = 1 (PRGENO = LOMEM) ;C = 0 {PRGENO ( LOMEM )
Prüfen , ob ein aktiver ONERRBefehl im Overlay liegt. Falls ja, wird er desaktiviert. BIT BPL LOA CMP LOA SBC BCC LSR
ERRF'LG NOONERR ERRAOR LOWTR ERRAOR+l LOWTR+l NOONERR ERRFLG
;Lo ;Hi ;löschen
Alle Strings, die zwischen OVSTART und dem Programmende liegen, müssen in den freien Speicher kopiert und ihr e Oeskriptoren entsprechend geä nd ert werden.
8. Speicher-Recycling = Overlay
935D : 935F : 9361: 9363: 9365 : 9367: 9369: 936B: 936D: 936F : 9371 : 9373: 9376:
A9 85 AO A6 A5 86 85 C5 DO E4 FO 20 FO
07 8F 00 69 6A 9D 9E 6C 04 6B 05 CC 93 F3
9378: 937A: 937C: 937E: 9380: 9382: 9384: 9386 : 9388: 938A: 938C:
86 85 A9 85 A6 A5 C5 DO E4 DO 4C
EB EC 03 8F EB EC 6E 07 6D 03 32 94
938F: 9391 : 9393 : 9395 : 9397: 9398: 939A: 939B : 939C: 939E: 93AO : 93A2 : 93A3: 93A5: 93A7: 93A9 : 93AA: 93AC: 93AD : 93AF 93B l 93B2 93B4
86 85 AO BI C8 51 08 C8 BI 65 85 C8 BI 65 85 28 10 C8 BI AO OA 69 65
9D 9E 00 9D 9D 9D EB EB 9D EC EC D4 9D 00 05 9D
175
165 166 Zuerst die einfachen Variablen (Skal aren) 167 LDA U07 ;7 Bytes Länge 168 NOONERR 169 STA DSCLEN ;init . 170 LDY UOO ;Beginn Skalare 171 LDX VARTAB 172 LDA VARTAB+l ;zwischenspeichern 173 STX DSCTMP 174 STA DSCTMP+l ;mit Beginn der Array175 SMPLLOOP CMP ARYTAB+l 176 BNE SAVESMPL CPX ARYTAB ;Variablen vergleichen 177 ;alle Ska l are fertig 178 BEQ SMPLDONE 179 SAVESMPL JSR SMPLSAVE ;immer 180 BEQ SMPLLOOP 181 182 Und nun auch die Felder (Arrays) 183 ;entspricht ARYTAB Lo 184 SMPLDONE STX TEMP ;entspricht ARYTAB Hi STA TEMP+l 185 ;Descriptorenl änge 186 LDA U03 ;eintragen 187 STA DSCLEN ;Adresse zurück Lo 188 NXTARAY LDX TEMP ; dito Hi 189 LDA TEMP+l ;sind wir fertig? CMP STREND+l 190 NXTVAR BNE ARYSAVE 19 1 CPX STREND 192 ;Nein BNE ARYSAVE 193 ;JA, lade neuen File JMP DOOVLY 194 195 ;als Zeiger merken Lo STX DSCTMP 196 ARYSAVE ; dito Hi STA DSCTMP+l 197 198 LDY UOO 199 LDA (DSCTMP), Y ; Name l. Byte INY 200 201 EOR (DSCTMP) , Y ;Name 2. Byte PHP ;Status merken 202 203 INY 204 LDA (DSCTMP), Y ; Offset Lo ;+ aktuel l e Adresse ADC TEMP 205 ;= Beginn der nächSTA TEMP 206 sten Variabl en INY 207 LDA (DSCTMP), Y ;Offset Hi 208 ADC TEMP+l ;+ aktue ll e Adresse 209 ;= Beginn nächst. Var. 210 STA TEMP+l ;Status zurück 211 PLP ; kein String! ! 212 BPL NXTARAY 213 INY 214 LDA (DSCTMP), Y ;Zahl der Dimensionen LDY UOO 215 216 ASL * 25 für Kopfteil 217 ADC U05 + 218 ADC DSCTMP + Startadresse
176 93B6: 93B8: 93B9 : 93BB: 93BD: 93BF : 93C l : 93C3: 93C5: 93C7: 93CA:
93CC: 93CE: 93DO : 93Dl : 93D3: 93D5:
8. Speicher-Recycling = Overlay 85 AA 90 E6 A5 C5 DO E4 FO 20 FO
BI 30 C8 BI 10 C8
9D 02 9E 9E EC 04 EB BD D6 93 F3
9D 50 9D 4B
93D6: BI 9D 93D8: FO 46
93DA: 93DB : 93DD: 93DE: 93DF: 93E l: 93E3: 93E5: 93 E8: 93EB: 93ED: 93EF: 93Fl: 93F3 :
93F5: 93F6: 93F7 93F9 93FA 93FB
C8 BI AA C8 BI 85 86 EC ED 90 E4 A5 E5 BO
9D 9D 9C 9B A5 95 A6 95 33 AF 9C BO 2B
88 88 BI 9D 48 38 A5 6F
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 24 1 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 27 1 272
NJETI NC ARYLOOP
RETARRAY
STA DSCTMP TAX BCC NJETI NC INC DSCTMP+l LDA DSCTMP+l CMP TEMP+l BNE RETARRAY CPX TEMP BEQ NXTVAR JSR STRGFND BEQ ARYLOOP
;=
1. Array-String Lo
;kein Übertrag ;weitersetzen ;De scr ipt or-Adr. Hi ;nächste Variable? ;retten ; Lo-By te ebenfall s ;also di ese Var. fertig ;String behandeln ; immer
Al le Strings im Overlay-Bereich mit Länge >0 sind gesuc ht. SMPLSAVE
LDA BMI INY LDA BPL INY
(DSCTMP),Y ;Name 1. Byte WEITER ; Int-Variabl e!/Fu nk tion! ;Name 2. Byte (DSCTMP), Y WEITER ;Real -Variab l e!
Se iteneinstie g für Arrayvariab l en STRGFND
LDA (DSCTMP),Y ; Länge des Strings BEQ WEITER ;= Null, übergehen
Liegt der Str in g im Overlay ? INY LDA TAX INY LDA STA STX CPX SBC BCC CPX LDA SBC BCS
(DSCTMP),Y ;Low-Pointer ;merken (DSCTMP),Y LOWTR+l LOWTR OVSTART OVSTART+l WEITER PRGEND LOWTR+ l PRGEND+ l WEITER
; Hi gh-Poi nt er ;zwisc hen spe i chern ;unter dem Ov er l ay? ;kann bleiben ;im Pro gramm? ; Hi zurück
Str in g liegt im Overlay-Bere ic h Se tze den Deskrip tor um und kopiere den Str in g unter FRETOP. DEY DEY LDA (DSCTMP), Y PHA SEC LDA FRETOP
;2 zurück auf Lä nge Länge laden zwisc henspe i chern Subtr . vorbereiten Unte rgre nze Stringpoo l
I
177
8. Speicher-Recycling = Overlay 93FD: 93FF: 9401 : 9402: 9404: 9406: 9407: 9409: 940B: 940D: 940F: 9411 : 9412 : 9413 : 9415 : 9417: 9419: 941B: 941D:
9420 : 9422: 9423: 9425: 9427: 9429: 942B: 942D: 942F: 9431:
9432: 9434: 9436 : 9438: 943A : 943C: 943E: 9440 : 9442 : 9444: 9446 : 9449: 944B: 944D: 944F: 9451: 9453 :
85 Fl C8 91 85 C8 A5 85 E9 91 85 68 18 65 85 A5 69 85 20
A5 18 65 85 90 E6 A6 A5 AO 60
A9 85 85 85 A9 85 A9 85 A9 85 20 A2 B5 95 B5 95 B5
94 9D 9D 6F 70 95 00 9D 70 9B 96 9C 00 97 9A D3
8F 9D 9D 02 9E 9D 9E 00
00 94 9C 97 69 9B 71 96 03 95 9A D3 01 69 9B 6D 96 6F
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
STA SBC INY STA STA INY LDA STA SBC STA STA PLA CLC ADC STA LDA ADC STA JSR
;Zielende Lo HIGHDS (DSCTMP), Y ;- Länge (DSCTMP), Y ;neue Lo-Adresse FRETOP ;Grenze herabsetzen FRETOP+l HIGHDS+l UOO (DSCTMP), Y FRETOP+l
;Untergre nze Stringpool ;Zielende Hi ; um Übertrag korrigieren ; neue Hi-Adresse eintragen ;S tringpool-Grenze neu ; Länge zurück
LOWTR HIGHTR LOWTR+l UOO HIGHTR+l BLTU2
;Anfangsadresse addieren ;Quellende Lo eintragen ; Quellende Hi eintragen ;Str ing verschieben
Zei ge auf den nächsten Eintrag WEITER
NOINC
LDA CLC ADC STA BCC INC LDX LDA LDY RTS
DSCLEN
;Länge des Deskriptors
DSCTMP DSCTMP NOINC DSCTMP+l DSCTMP DSCTMP+l UOO
;zum letzen dazuzählen ;neue Adresse eintragen ;kein Übertrag ;Hi-Adresse weiterzählen ;für Bere i chsüberprüfung ; jetzt laden ;Z-Flagge setzen ;zurück, nächster String
Gesamte Variablen tabelle nach oben unter FRETOP schieben. Pointer in den Tastaturpuffer retten DOOVLY
VARMOVE
LDA STA STA STA LDA STA LDA STA LDA STA JSR LDX LDA STA LDA STA LDA
UOO HIGHDS LOWTR+l HIGHTR+l U69 LOWTR U71 HIGHTR U03 HIGHDS+l BLTU2 U Ol VARTAB,X LOWTR ,X STREND,X HIGHTR ,X FRETOP ,X
;Zielende Lo ; Quellanfang Hi ;Que llende Hi ; Que ll anfang Lo ;Quellende Lo ;Zielende Hi ;$69-$70 - } $2F8-$2FF ;Begi nn Skalare Quellanfang ;Ende der String-Var. ;= Quellende ;Untergrenze Stringpool
;=
178 9455 : 9457: 9458: 945A: 9450: 945F : 9461 : 9463 : 9464 :
8. Speicher-Recycling = Overlay 95 CA FO 20 A5 85 A6 E8 86
94 Fl 9A 03 94 EO 95 EE
9466: 20 95 AO
9469: 20 7B 00 946C: 20 6C 00
946F: 9471: 9473: 9474: 9475: 9477: 9479: 947A: 947C :
AO Bl AA C8 Bl 85 C8 Bl 85
947E: 947F : 9481 : 9483 : 9485:
CA 30 EO 90 4C
9488: 9489: 948A: 948C: 948E: 9491 : 9492:
8A A8 Bl 09 99 88 10
00 AO AO 90 AO 9E
04 30 03 C9 OE
90 80 75 AA F6
9494: 20 FO E5
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
STA OEX BEQ JSR LOA STA LOX INX STX
HIGHOS,X VARMOVE BLTU2 HIGHOS TEMP2 HIGHOS+l TEMP2+1
;=
Zielende
; VariablenjStringzeiger ;neuer Anfang Lo ;merken ; (neuer Anfang Hi )-l ;korrigieren ;merke n
Der zu lesende File muß geöffnet werden, um se ine Länge zu bestimmen. JSR CLRFNBUF
;Namenspuffer lö schen
Filenamen überprüfen JSR FRMEVL JSR CHKSTR
; auswer ten ;String?
FACMO enthält Zeiger auf Oeskriptor LOY LOA TAX INY LOA STA INY LOA STA
UO O (FACMO),Y
;Länge ;re tten
(FACMO),Y OSCTMP
;Lo
(FACMO),Y OSCTMP+l
;Hi
(OSCTMP) zeigt auf String. Kopiere ihn in den Filenamens puffer.
ERROR NAMEOK COPY
OEX BMI CPX BLT JMP TXA TAY LOA ORA STA OEY BPL
;0
;Syntax-Error ;X->Y
(OSCTMP) , Y #$80 ;Bit 7 setzen FNBUF1 , Y COPY
kopierten String wieder freisetzen JSR FRESTR File-Mana ger-Parameterli s te initialisieren
8. Speicher-Recycling = Overlay
9497: 20 89 FE 949A : 20 93 FE 949D : 20 AE Al
94AO: 94A3: 94A5: 94A7:
20 A5 DO 4C
64 A7 45 03 C8 A6
94AA: 85 41 94AC : A5 44 94AE : 85 40
94BO: 20 43 A7 94B3: 20 4E A7 94B6: 20 lA A7
94B9 : A2 01 94BB : 8E BB B5 94BE : 20 D6 03
94Cl: 90 06 94C3 : AD C5 B5 94C6 : 4C D2 A6 94C9 : 94CC: 94C E: 94DO: 94D2: 94D4:
94D6 : 94D9: 94DA : 94DD : 94DE: 94DF: 94E2: 94E4: 94E6:
AD 29 C9 FO A9 DO
20 18 60 AA 98 6D C5 90 4C
C2 B5 7F 02 04 OD FO
7A A4 A5 95 A6 95 EE 03 CC A6
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
179 JSR SETKBD JSR SETVID JSR ZEROPRMS
;DOS aus dem Daten;ver kehr ausschließen
Freien DOS-Puffer suchen JSR LDA BNE JMP BUFOK
GETBUF NXTBUF+l BUFOK NOBUFS
STA CURBUF+l LDA NXTBUF STA CURBUF
; jetziger Puffer
Filenamen kopieren, Liste vervol l ständigen JSR COPYFN JSR COPYBP JSR CMPLPRMS
;Pufferze i ger ;Parameter
Jetzt File öffnen (nicht anlegen) LDX #$01 STX FMPL JSR FMGR Auf Fehler und Filet yp prüfen
FEHLER OKAY
BCC OKAY LDA FMPL+$A JMP DOSERR LDA AND CMP BEQ LDA BNE
FMPL+$7 #$7F #$02 FILEOKAY #$O D FEHLER
;Feh 1ertyp
;Lock-Bit ausb l enden
;immer
File ist offen, bestimme/prüfe Länge FILEOKAY
JSR CLC ADC TAX TYA ADC CMP BCC JMP
RD2BYTE OVSTART ;merken ;Hi-Byte Länge OVSTART+l TEMP2+1 SIZEOK TOLARGE
Jetzt File e in lesen
;genug Platz?
180 94E9: 94EC : 94EF' : 94F'2:
8. Speicher-Recycling = Overlay AE AC 20 20
A5 A6 71 EA
95 95 A4 03
94F'5: 94F'7: 94F'A: 94F'C: 94F'F': 9501 :
A5 CD A5 ED 90 20
7D A5 95 7E A6 95 03 49 D8
9504: 9507: 9509: 950B : 950D : 950F': 9510: 9512: 9514: 9516: 9518: 9519: 951B: 951D: 951E: 951F': 9521: 9522: 9524: 9526 : 9528: 952A : 952B : 952D: 952F' : 9531 :
20 A5 A4 85 84 18 AO BI F'O AO C8 BI DO C8 98 65 AA AO 91 A5 69 C8 91 86 85 90
83 D6 67 68 5E 5F'
9533: 9534: 9536: 9538: 953A : 953C: 953E : 9540 : 9542:
18 A5 69 85 85 A5 69 85 85
01 5E ID 04 5E F'B 5E 00 5E 5F' 00 5E 5E 5F' DD
5E 02 AF' 69 5F' 00 BO 6A
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
SIZEOK
OVSTART OVSTART+l F'ILEREAD CONNECT
; Ladeadresse La Hi ;DOS anhängen
Wenn DATA-Zeiger im Overlay. Restare ausführen Die Linkadressen neu berechnen (dem AS- ROM entlehnt) LDA DATPTR CMP OVSTART LDA DATPTR+l SBC OVSTART+l BCC NOREST JSR RESTORE NOREST
LI NKLOOP
ENDLOOP
477
478 479 480 481 482 483 484 485 486 487 488 489 490
LDX LDY JSR JSR
J SR STKI NI LDA TXTTAB LDY TXTTAB+l STA INDEX STY INDEX+l CLC LDY #$01 LDA (INDEX), Y BEQ LINKEND LDY #$04 INY LDA (INDEX), Y BNE ENDLOOP INY TYA ADC INDEX TAX LDY #$00 STA (INDEX), Y LDA INDEX+l ADC #$00 INY STA (INDEX), Y STX INDEX STA INDEX+1 BCC LINKLOOP
;Pragrammanfang ;Zeiger
;alte Adresse Hi ; Offset ;Ze ilenende suchen ; Zeilenlänge ; merken ;ei ntragen ;ev . Übertrag ;eintragen ;Zeiger weitersetzen ;immer
Zeiger herste llen LINKEND
CLC LDA ADC STA STA LDA ADC STA STA
INDEX #$02 PRGEND VARTAB INDEX+1 #$00 PRGEND+l VARTAB+1
;Übertrag?
8. Speicher-Recycling
9544 : 9546: 9548: 954B: 9540: 9550: 9552:
24 30 AD C5 AD E5 90
EF' 18 F'8 02 AF' F'9 02 BO OC
9554: 9556: 9559: 955B: 955C: 955E:
A2 BD 95 CA 10 30
05 F'8 02 69
9560 : 9561 : 9563: 9566: 9568: 956A: 9560: 956F': 9571: 9574 : 9575: 9578: 957A : 9570: 957F': 9581: 9583 : 9585: 9587: 9589: 958A: 958C: 958E:
38 A5 ED 85 A5 ED 85 A2 20 E8 20 A2 BD 95 95 B5 95 B5 95 CA F'O AO 20
F'8 18
69 F'8 02 90 6A F'9 02 9E F'A 94 95 94 95 01 F'E 02 6F' 3E ED 3C 69 42 EE 00 2C F'E
9591: 4C 02 07 9594: 18 9595: BD 00 02
=
Overlay
181
491 492 Wenn der a lte LOMEM-Wert gerettet 493 werden sollte , ist dieser zu über494 nehmen , wenn das mit dem neuen 495 Programmende noch möglich ist. 496 497 BIT LOMEMF'LG 498 BMI NOSAVE 499 LDA $2F'8 ;altes LOMEM 500 CMP PRGEND 501 LDA $2F'9 502 SBC PRGEND+l BCC NOSAVE ;nicht möglich 503 504 LDX U 05 505 506 SAVELOOP LDA $2F'8 , X 507 STA VARTAB,X 508 DEX 509 BPL SAVELOOP 510 BMI MOVESTR 511 512 513 Die Zeiger sind neu zu berechnen 514 515 NOSAVE SEC 516 LDA VARTAB ; neuen VARTAB-Wert ;alten Wert abziehen 517 SBC $2F'8 518 STA DSCTMP ;merken LDA VARTAB+l ;dito für Hi-Byte 519 SBC $2F'9 520 STA DSCTMP+l ; (Differenz Programmenden) 521 ;alter ARYTAB- Wert 522 LDX U F'A ; neuen Wert berechnen JSR ADDDIF' 523 ; insgesamt +2 524 INX ;auch für STREND JSR ADDDIF' 525 526 MOVESTR LDX *$01 ;alter F'REETOP 527 COPYLOOP LDA $2F'E , X STA F'RETOP,X ; umkopieren 528 STA A2L,X ; Quellbereichs-Ende 529 LDA TEMP2,X ;Quel l bereichs-Anfang 530 531 STA A1L , X ;für MOVE eintragen ;Zielbereichs-Anfang 532 LDA VARTAB,X STA A4L,X 533 534 DEX 535 BEQ COPYLOOP 536 LDY U OO 537 JSR MOVE ;VariablenjDescr. versch. 538 539 Den nächsten Befehl ausführen 540 54 1 JMP NEWSTT 542 543 ADDDIF' CLC 544 LDA $200,X ;ARYTAB bzw. STREND Lo
8. Speicher-Recycling == Overlay
182 9598: 959A: 959C : 9590: 95AO: 95A2: 95A4:
65 95 E8 BD 65 95 60
90 71 00 02 9E 71
95A7: 2C 4C 56
545 546 547 548 549 550 551 552 553 554 555
ADC STA INX LDA ADC STA RTS
DSCTMP $71,X $200,X DSCTMP+l $71,X
OVSTART
DfS 2
AUfRUf
ASC ' , LVO'
;+ Differenz ; Offset +$71 - » $6B , $60 ;Hi-Byte ; alter Wert ;+ Differenz ;Offset +$71 - » $6C , $6E ;zurück
; "OVL,"
Diese Demonstration , die einer Demo aus Nibble 4/1984 Seite 78 nachempfunden ist, benutzt nur 2 Overlays , die Teile des Grundmoduls überschreiben. Sie können sich durch das Programm jeweils die Zeilen im Speicher listen lassen, um die aktiven Programmzeilen zu sehen. OVL-DEMO 5 TEXT: PRINT CHR$ (21): HOME 10 INVERSE : HTAB 12: PRINT " OVERLAY - DEMO ": NORMAL 20 HTAB 6: PRINT "(C) 1986 DR. JUERGEN KEHREL": POKE 34 , 3 30 PRINT CHR$ (4)"BLOAD OVL-MANAGER.OBJ": CALL 37632 40 VTAB 4 : PRINT "DIESE DEMONSTRATION SOLL IHNEN EINEN" 50 PRINT "KLEINEN EINDRUCK VON DEN MOEGLICHKEITEN" 60 PRINT "DES OVERLAY-MANAGERS VERMITTELN." 70 PRINT: PRINT "DIE PROGRAMMZEILEN AB 500 WERDEN NACH" 80 PRINT "UND NACH ERSETZT, OHNE DASS VORANSTEHEN-"; 90 PRINT "OE ZEILEN ODER VARIABLEN VERLOREN GEHEN." 100 GOSUB 450 140 VTAB 12: CALL - 958 150 PRINT "WIR WERDEN DIESE ZEILEN JETZT AUS-" 160 PRINT "fUEHREN": fOR 1=1 TO 2500: NEXT I 170 GOSUB 500: HOME : VTAB 7: PRINT "WIR LADEN EINE SORTIERROUTINE." 180 PRINT 190 & OVL,500,"SORTER" 200 PRINT "AB ZEILE 500 STEHT JETZT EIN SORTIER-" 210 PRINT "PROGRAMM IM SPEICHER." 220 GOSUB 450: VTAB 12: CALL - 958 230 PRINT "IHRE EINGABEN WERDEN SORTIERT!" 240 GOSUB 500 250 HOME: VTAB 7: PRINT "WIR LADEN EINE AUSGABEROUTINE NACH." 260 & OVL,500 , "PRINTER" 270 PRINT : PRINT "AB ZEILE 500 STEHT JETZT EIN AUSGABE-" 280 PRINT "PROGRAMM IM SPEICHER." 290 GOSUB 450: VTAB 12: CALL - 958 300 GOSUB 500: PRINT : PRINT "MIT LIST KOENNEN SIE SICH DAS ZUSAMMEN-" 310 PRINT "GESETZTE PROGRAMM ANSEHEN.": POKE 34,0: VTAB 20: END 450 VTAB 12: PRINT "AUGENBLICKLICH LAUTEN DIE ZEILEN SO:" 460 VTAB 13: fOR I = 1 TO 40: PRINT "_" ; : NEXT 470 LIST 500 , 600 480 GET C$ 490 RETURN 500 REM EINGABEROUTINE 510 HOME: PRINT "BITTE GEBEN SIE 10 ZEICHENKETTEN EIN:"
8. Speicher-Recycling = Overlay
520 530
183
FOR I = 1 TO 10: PRI NT I;: HTAB 5 : INPUT A$(I) : NEXT RET URN
Overl ay-Modul "SORTER"
500 510 520 530 540 550
REM SO RTI ERT DATEN IN A$() FOR 1 =2 TO 10 : PRI NT "." ; FOR J = 1 TO I IF A$( J ) < = A$( I ) THEN 550 T$ = A$( I ) :A$(I) = A$ (J ) :A$( J ) = T$ NEXT J,I : RETURN
Overlay-Modul "PRINTER"
500 510 520 530
REM AUSGABE DER DATEN IN A$() FOR I = 1 TO 10 PRINT I;: HTAB 5 : PRINT A$( I ) NEXT I : RETURN
Der "Appl esoft- Overl ay-Ma nage r" ge hört schon in die Klasse d er komplexeren Programme . Aus diesem Grunde wurde das Gesamtprogramm in viele klein e A bschnitte eingeteilt , die eine Fun ktion erfü)l en un d jewei ls eine eigene Ü berschriftszeile besitze n . Wegen der Länge des Programms ist es nicht möglich , jedes einzelne Byte jetzt noch einm al extra zu beschreiben. Sie so ll te n die zahlreichen Ko mmentare im Listin g beachten. Diese sin d im übrigen nicht deshalb so ausführlich , wei l das Progra mm ve röffentlicht wird. A uch meine "priva ten" Schöpfungen ve rsehe ich reichlich mit Bemerkungen, weil ich sonst nach einem Ja hr selber nicht mehr durch meine Werke "durchblicke" . A uch we nn Kommentare zu nächst viel T ipparbeit bedeuten, machen sie sich bei notwendigen Ve rbesserungen oder E rgä nzu ngen schn ell beza hlt. Nach dem A ufruf aus dem BASIC-Programm beginnt die A usführung ab OVER LA Y (Zeile 110) . Hier wi rd zu nächst zwangsweise die A ppl esoft-Garbage-Collection aufge rufe n, die alle Strings im Stringpoo l - zw ischen FRETOP und HIMEM: - fe in säuberlich unterh alb von HIMEM : anordnet sowie all e "Stringleichen" entfe rnt. Mit der schon beschriebenen Ro utine SYNCHR ($DECO) ve rgleichen wir , ob dem & die Zeichen "OVL" fo lgen. Wenn dies nicht de r Fall ist , erhalten wir die Fehlermeldu ng "SYNTAX E R ROR", andernfalls wird mit CHKCOM ($DEBE) das Ko mma geprüft und übersprungen. TXT PTR zeigt da nn auf das erste Zeichen de r Zeilennummer , di e mi t LI NGET ($D AOC) vo n ihrer ASCII-codi erten Form in eine 2-Byte-Hex-Zahl in LINNUM ($00500/51) ve rwa ndelt wird . FNDLIN ($D61A) liest diesen We rt und sucht die zugehörige Zeile im Programmspeicher (im BASIC-Progra mm ) . E xistiert die Z eile nicht , wird stat t der Ze il enad resse die Adresse der nächsth ö-
184
8. Speicher-Recycl ing = Overlay
heren Zeile oder das Programmende in LOWTR übergeben, fa lls keine Zeile mehr folgt.
LINGET $DAOC We rtet eine Z ahl (0-63999) an der TXTPTR-Stelle aus und wa ndelt sie in eine H EX-Zahl ohne Vo rzeichen E inga be: TXTPTR zeigt auf 1. Zeichen, das sich auch im Ak ku befinden mu ß (z.B. durch JSR CHRGOT). Bit 7 im ASCII-String mu ß 0 sein. A usgabe: LINNUM ($0050/51) = ausgewertete Zahl (Lo/H i)
FNDLIN $D61A Sucht die in LINNUM angege bene A pplesoftzeile Einga be : LINNUM ($0050/51) Z eilennummer (Lo/H i) A usgabe: Carry gelöscht , wenn Zeile gefunden Carry gesetzt , wenn Zeile nicht gefunden LOWTR ($009B/9C) Adresse des Zeilenanfa ngs bzw. der näc hst höheren Zeile (ev. Progra mmende)
Wenn Sie mit hochauflöse nder G rafik arbeiten, ist es üblich , LOMEM hochzusetzen , dami t die Variablen erst oberhalb der Grafikseite(n) beginnen. Nach dem E inladen des Overl ays wird das neue LOME M entweder a) hinter das neue Programmende gelegt , wenn es vo rher auch do rt war , b) auf seinen alten We rt gesetzt , wenn es vo rher nicht mit dem Programmende identisch war. D er Fall a) ist die Normalsituation und recht einfach zu bewerkstelli gen . Der Fall b) ist interessanter. Wenn Sie LOMEM hochgesetzt habe n, wird dies in den Z eilen 140ff festgestellt und vermerkt. Nach dem Laden des Overlay wird
8. Speicher-Recycling = Overlay
185
getestet , ob das neue Programmende unterhalb des alten LOMEM liegt. Ist das der Fall , wird LOMEM wieder hergestellt (Zeilen ab 497) . Ist das Programm aber so lang geworden , daß der alte LOMEM-Wert überschritten wird , so wird das neue LOMEM an das Programmende gelegt. Durch diesen etwas komplizierten Verlauf ist gewährleistet , daß LOMEM niemals fälschlich innerhalb des BASIC-Programms liegt , daß es aber auch nicht in die Grafik rutscht , wenn es vorher darübergelegt worden war. Die Prüfung eines aktiven ONERR wurde bereits besprochen. Bevor nun das neue Modul eingelesen werden kann , müssen noch ein ige Zeichenketten gerettet werden. Applesoft verfrachtet nämlich nicht alle in den Stringpool , sondern setzt den Zeiger in das BASIC-Programm , wenn eine Zeichen kette dort direkt definiert wurde . Nehmen wir ein Beispiel: 10 A$ = "HALLO" Jetzt würde der Zeiger in den BASIC-Text weisen. 20 B$ = A$ + " SIE DA" B$ ist zusam mengesetzt und wird im Stringpool abgelegt. Wenn nun einige direkt definierte Zeichen ketten im Overlay-B ereich liegen , müssen sie vor dem Laden des neuen Moduls aus dem BASIC-Programm in den Stringpool kopiert werden, um erhalten zu bleiben. A ll e Zeilen vo n 168 bis 305 machen nichts anderes , als sowohl die Tabelle der einfachen als auch der Feldvariablen nach Strings zu durchsuchen , bei denen der Zeiger im Deskriptor in den Overlay-Bereich weist. Wird ein solcher gefunden, wird er unter den bislang letzten String kopiert und FRETOP entsprechend erniedrigt. Da dies immer eine Verschiebung von unten nach oben ist , benutzen wir die Routine BLTU2 ($D39A) dazu.
BLTU2 $D39A Verschiebt den Speicherbereich von LOWTR (Anfang) bis HIGHTR (altes Ende) nach HIGHDS (neues Ende). Nicht geeignet für Verschiebung nach unten und Überschneidung von Quell- und Zielbereich. Eingabe: LOWTR ($009B/9C) = Zeiger auf Quell anfang HIGHTR ($0096/97) = Zeiger auf Quellende HIGHDS ($0094/95) = Zeiger auf Zielende Ausgabe: -
186
8. Speicher-Recycling = Overlay
Da das neue Modul das Programm verkleinern oder vergrößern kann , werden jetzt die Variablen tabellen zwischen LOMEM und STREND bis unter FRETOP geschoben (wieder mit BLTU2) und das untere Ende vermerkt. Bis dorthin ist im äußersten Fall Platz für das Overlay. Die alten Zeiger auf der Zero-Page werden in das obere Ende des Tastaturpuffers gerettet. Jetzt ist es Zeit, de n neue n Fi le zu lesen. Wir benutzen dazu einige Routinen von DOS 3.3 direkt. Da diese nicht von Apple dokumentiert sind , besteht keine Gewähr , daß sie bei Derivaten wie z.B. Diversi-DOS an der sei ben Stelle liegen. Falls das Programm bei Ihnen einmal nicht läuft , versuchen Sie es vor einer Fehlersuche erst mit normale m DOS 3.3. Bevor nun der File gelesen wird , stellen wir vorsichtshalber seine Länge fest und vergleichen diese mit dem frei e n Platz im Speich er. Ist zuwenig Platz , gibt es eine Feh lermeldung . D ie Länge des Files finden wir bei einem Applesoft-Programm in den ersten beide n Bytes des Files. Um diese zu lese n , müssen wir den File öffnen . Das ist etwas ande res als ein " OPEN " für Textfiles , da hierbei lediglich die Filepuffer und -Zeiger eingerichtet werden. Damit wir wissen , welchen File wir öffnen sollen , müssen wir seinen Namen einlesen. FRMEVL ($DD7B) besorgt dies . Da FRMEVL aber nicht nur Zeichen ketten auswertet , folgt mit CHKSTR ($DD6C) ein Test, ob wirk lich eine Z eiche n kette ge lesen wurde . Ist das der Fall, wurde in $OOAO bis $00A2 ein vorläufiger Deskriptor angelegt. Wir benutze n diese Information , um den Filenamen in den Fi lenamens-Puffer des DOS zu kopieren , nachdem der Puffer vorher mit CLRFNBUF ($A095) mit Leerzeichen aufgefüllt worden ist . Für die weitere Bearbeitung muß Bit 7 gesetzt sein , was wir beim Kopieren mittels ORA #$80 gleich miterledigen. Der vorläufige Deskriptor wird danach mit FRESTR ($E5FD) wieder freigesetzt , damit er nicht auf dem Deskriptoren-Stack verbleibt.
FRESTR $ESFD Entfernt einen String aus dem Stringpool (falls dort zuunterst) und löscht gegebenenfalls den Eintrag im Deskriptoren-Stack . Eingabe: VALTYP ($0011) muß $FF sein Ausgabe: Akku = Stringlänge X-RegN-Reg = Zeiger auf Strin g (Lo/Hi)
8. Speicher-Recycling = Overlay
187
Da DOS jetzt direkt aufgerufen we rden soll , wird DOS aus dem Datenverkehr über die CSW- und KSW-Vektoren ausgeschlossen .
SETKBD $FE89 KSW wird auf $FD1B (KEYIN) gesetzt (= IN *'0) E ingabe: A usgabe: KSWLlH ($0038/39) enthält $FD1B
SETVID $FE93 CSW wird auf $FDFO (COUTl) gesetzt (= PR *'0) Eingabe: A usgabe: CSWLlH ($0036/37) enthält $FDFO
Für unsere weitere Bearbeitung des F iles benutzen wir einen Teil des DOS, der File-Manager genann t wird . Dieser kann durch einen Vektor auf der Seite 3 mittels JSR $03D6 aufger ufen werden. Damit der Fi le-Manager weiß , was er tun so ll , muß vo rher eine Parameterliste aufgefü llt werden. Die A nfangsadresse dieser Liste finden wir durch ein JSR $03DC. Y-Register (Lo) und Akkumulator (Hi) bringen die Anfangsadresse zu rück, die wir dann z.B . auf der Zero-Page speichern können , um sie für die indirekte indizierte Adressieru ng zu benutzen, denn alle A nga ben in der Parameterliste erfo lgen relativ zu ihrem Beginn. In unserem "Applesoft-Overlay-Manager" habe ich etwas unsauber programmiert und gleich die Standardadresse $B5BB für normales 48K-DOS benutzt, da auch die ande ren Direktaufrufe nur mit diesem DOS funktionieren (nich t mit verschobenem DOS!). ZEROPRMS ($A1AE) löscht die Parameterlister des File-Manage rs. Ansch li eßend müssen wir einen freien Fil e-Puffer suchen. GETBUF ($A764) erledigt di es und schreibt die Adresse nach NXTBUF ($0044/45). Ist das Hi-Byte gleich Nu ll , ist kein Puffer mehr frei und wir geben die Feh lermeldung "NO BUFFERS A VAILABEL" aus (NOBUFS $A6C8). Für den File-Ma nage r kopieren wir die gefundene Pufferadresse nach $0040/41 (CURBUF) . COPYFN ($A743) kopiert den Filenamen aus dem Filenamenspuffer des Fi le-Ma nage rs in den
188
8. Speicher- Recycling = Overlay
gefundenen File-Puffe r und deklari ert diesen damit als belegt. COPYBP ($A 74E) überträgt aus dem File-Puffe r einige Zeiger in die Parameterliste. D ies sind: Adresse des File-Manage r- Arbeitsbereich, Adresse des TSL-Puffe rs (für Track-Sektor-Liste des Files) , Ad resse des Date npuffers, Adresse des nächsten File-Puffers . Wir brauchen uns um die E inrichtung dieser Puffe r nicht zu kümmern . CMPLPRMS ($A 71A) vervo llstä ndigt die Parameterliste weiter. Jetzt kommt der spannende Moment. Das erste Byte der Para meterliste e nthält das Befehlsbyte . Für "OPEN" muß do rt $01 stehen. Daß wir das X-Register für dieses Laden benutzen , hat noch einen weite ren Effekt. We nn der aufge rufe ne File noch nicht existiert , legt der File-Manage r einen Fi le an, we nn das X-Register beim A ufruf gleich Nu ll ist. Da wir dies hier nicht wollen, verhindert das Laden des X-Registers mit $01 gleichzeitig auch die Ne uanl age ein es Fi les. Ist nach dem JSR FMGR das Carry-Bit gelöscht, war die A ktion erfo lgreich , un d wir kö nnen weitermachen. Im andere n Fall finden wir im zehnte n ($OA) Byte der Pa rameterliste die Fehlernummer, di e wir dazu benutze n, über D OSER R ($A6D2) eine Fehl ermeldung auszugeben . Im sie bten Byte der Parameterliste finden wir de n Fil etyp des geöffneten Files. Bei A ppl esoft muß es $02 oder $82 bei einem "gelockten" File sein . Der Fehl er $OD bede utet "FILE TYPE MISMATCH " . Mehr darüber in Kapitel 9.1. Mit H ilfe vo n RD2BYTE ($A47 A) lesen wir die ersten beiden Bytes des geöffneten Files, die ja die Filelänge enthalten. Reicht der P latz nicht , wird ein e Meldung ausgegeben. Z um eist wird aber gen ügend RAM frei sein , und wi r können über FILEREAD ($A471) den gesamten Rest des Files hereinh olen. D amit der File-Ma nager auch weiß , wo hin alles gelesen werden soll , müssen wir in den Indexregistern (X-Reg = Lo , Y-Reg = H i) die gew ün schte Ladeadresse übergeben. FILER EAD ist auch so fre undlich und schließt automatisch den File für uns, so daß wir die Puffe r nicht selber freigeben müssen. Mit CONNECT ($03EA) hängen wir DOS 3.3 wieder an , indem die CSW- und KSW-Vekto ren zurückgesetzt werden. Beim Lesen vo n DATA-Zeilen merkt sich Applesoft , welches E lement zu letzt gelesen wurde. Wenn der DAT A-Zeiger (DATPTR $007D/7E) in das OverlayGeb iet zeigt, ist er jetzt nicht mehr gültig. Wir füh re n des halb zwangsweise ein RESTORE ($D849) durch.
8. Speicher-Recycling = Overlay
189
RESTORE $D849 Setzt den DATA-Zeiger auf den Programmanfang E ingabe : Ausgabe: DATPTR ($007D/7E) = TXTTAB - 1
Wir sind jetzt fast fertig. Der neu hinzugeladene Tei l muß nur noch mit dem alten Teil verknüpft werden, indem alle Zeiger auf die Zeilenanfänge neu berechnet werden. Die ROM-Routine von Applesoft können wir diesmal nich t benutzen, da sie nicht zurückkehrt. Wir bilden sie deshalb modifiziert in unserem Programm nach. STKINI ($D683) setzt den Stackzeiger auf $F8 . Dadurch werden all e RETURN-Adressen gelöscht . Die Folge ist, daß bei ei nem Aufruf des "Applesoft-Overlay-Managers" keine offenen GOSUBs mehr bestehen dürfen.
STKINI $D683 Initiallisiert Stackzeiger E ingabe: Ausgabe: Stackzeiger = $F8
Das neue Setzen vom LOMEM haben wir bereits besprochen. Die Variab lentabellen, die bis jetzt unter FRETOP hingen, werden wieder bis zum neuen LOMEM-Wert nach unten geschoben. Für diese Versch iebung nach unten benutzen wir die Routine MOVE ($FE2C). Interessant ist ferner die Neuberechnung der diversen Zeiger , die im Tastaturpuffer zwischengespeichert waren.
190
8. Speicher-Recycling = Overlay
MOVE $FE2C Verschie bt den Speicherbereich zwischen A1L1H ($003C/3D) und A2L1H ($003E/3F) zur Zieladresse A4L1H ($0042/43) Eignet sich nicht zur Verschi ebung nach oben bei Bereichsüberschneidung. Eingabe: A1L1H ($003C/3D) = Startadresse (Lo/Hi) A2L1H ($003E/3F) = E ndadresse (Lo/Hi) A4L1H ($0042/43) = Zieladresse (Lo/Hi) Y-Reg = $00 (wichtig!) A usgabe: Carry gesetzt
E ine allerletzte Zeile fehlt uns noch. NEWSTT ($D7D2) springt zurück ins A pplesoft-Programm und führt den nächsten Befehl nach unserem A mpersa ndAufruf durch.
NEWSIT $D7D2 Führt nächsten Applesoft-Befehl aus. Eingabe: TXTPTR zeigt auf das letzte Zeichen vor dem neuen Befehl (,, :" oder EOL)
191
9 . Blitz-Leser Falls Sie schon einmal mit CP/M gea rbeitet habe n , werden Sie sicher de n TYPE-Befeh l kennen , mit de m Sie sich Textfi les ansehen könne n. Unte r DOS besitzen wir derartige Möglichkeite n nicht. Wir benötigen zum Lesen von sequentielle n Textfiles ein eigenes Programm. Dafür werden wir es aber a uch komfortabler gestalten als das TYPE. Bedienungsan leitungen zu Programmen sind oft als Textfi les abgespeiche rt. Auch ma nch e Textverarbeitungsprogramme erzeugen reine Textfiles. U nser schneller File-Leser wird diese Tex te wie der Blitz vo n de r Diskette lesen und auf de n 40Z/Z -Bildschirm a usgeben. Mit der Rechts- und der Linkspfeil-Taste können Sie die Geschwindigkeit der Ausgabe steue rn , um sie Ihren Lesegewohnheiten a nzupasse n. An be iden Enden der Verstellmöglichkeit macht Sie ein Ton darauf a ufmerksam, daß Sie das Max imum e rreicht habe n . Di e Leertaste stoppt die A usgabe zeitweise , mit <ESC> kön nen Sie sie abb rechen . E in Drücken vo n sprin gt zur schn ellstmöglichen A usga be . D ie Idee zu diesem Programm kam mir beim "File-Reade r" von Ulrich Stiehl (Apple DOS 3.3 , Seite 186 der 2. A uflage). Ich habe dieses Programm häufig benutzt, und Sie werden bei der Bildschirmausgabe einige Ähnlichkeiten e ntdecken kö nn en. Zwei Dinge habe n mich gestö rt : 1) Die Geschwindigkeit ist nicht gut regulierbar. Hier ist die Abhi lfe leicht möglich . 2) Die Diskette mit de m Textfile darf nicht schreibgeschützt sein. Dieses Problem ist schon schwieriger. U lrich Sti ehl wendet den vo n ihm e rdachte n "UNLOCK"-T rick an , um auf einfache Weise in den Besitz der T rack-Sektor-Liste (TSL) des Fi les zu kom men. UNLOCK schreibt aber auf die Diskette, auch wenn de r File nicht ges perrt sein so llte . Wenn wir den scho n aus dem le tzten Kapitel bekannten Fi le-Ma nager einsetzen, kö nne n wir mit relativ gerin gem Mehraufwand auch a n die TSL herankomm e n , ohne da ß dazu ein Schreibzugriff nötig wäre. Das Kommando " OPEN" des
192
9. Blitz-Leser
File-Managers (Achtung, nicht identisch mit dem DOS-Befehl OPEN ') liest ebenfalls die erste TSL des eröffneten Files ein. Die weitere Arbeit lassen wir durch einen zweiten Programm teil des DOS machen. Die RWTS (Read/Write Track/Sektor) liest ganze Sektoren in den Speicher. Dies geschieht über die RWTS bis zu 15-mal schneller als mit norm alen DOS 3.3-Kommandos , die viel Zeit für Ve rwa ltungsaufga ben verlieren. Nebenbei bemerkt: ProDOS besitzt schnellere Schreib- und Leseroutinen (RWTB = Read/Write Track/Block) als DOS , betreibt aber ein en noch größeren Verwaltungsa ufwa nd , so daß diese Vorteile zum Teil wieder ve rloren gehen. Wie für den File-Manager müssen wir auch hier eine Parameterliste anlegen und Vektoren auf der Seite 3 benutzen. Bevor wir dies im einzelnen besp rechen, könn en Sie sich jetzt schon in das Listing vertiefen.
A bb . 11: Ve rein fac hter A bl aufpl an des schne lle n Fil e-Lese rs
8. Blitz-Leser
FILELESER
193 1 2 3 4 5 6 7 8 9 10 11
0803 0804 0807 080A
D8 20 2F FB 20 58 FC A9 07
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
;******************************* Schne ll er File-L eser für * Text- Fi l es * (C) 1986 Dr. Jürgen Kehrel * ;******************************* Version 2.0
PTRIOB PTRFMPL PTRTSL PTRTRK PTRPUF YSAVE CH PROMPT PREG PTRPRT
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
$0000 $0002 $0004 $0006 $0007 $0009 $0024 $0033 $0048 $OO CE
IN
EQU $02 00
DOSCLD FLEMGR RWTS GETFMPL GETIOB CONNECT
EQU EQU EQU EQU EQU EQU
PUFFER
EQU $1000
KBD STROB E
EQU $COOO EQU $C010
TEXT TABV BELL CLREOP HOME WA I T RDKEY GETLN SETKBD SETVID COUT
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
;+$0001 ;+$0003 ;+$0005 ;+$0008 ;Cursor horz. ;Prompt ;P-Regis t er ;+$OOCF ; Tastaturpuf.
$03D3 $03D6 $03D9 $03DC $03 E3 $03 EA
$FB2F $FB5B $FBDD $FC42 $FC58 $FCA8 $FDOC $FD6A $FE89 $FE93 $FDED
;$10 00 - $8AFF
;Position ; Lösche n ;Warteschleife ;Taste le se n ; Zeile le se n
ORG $803 Titel und Menü ausgeben START
CLD J SR TEXT JSR HOME LDA n
; Binärmode
194
9. Blitz-Leser
080C: 080E: 0810: 0813: 0816: 082E: 082F: 0831 : 0833: 0835: 0838: 083B: 084B: 0855: 0857: 0859: 085B: 085E: 0864: 0866: 0868: 086A: 0860: 0870: 0872: 0875: 0877: 0878:
85 A9 20 20 AA 00 A9 85 A9 20 20 06 AO 80 A9 85 20 A8 80 A2 A9 20 AO 10 80 30 CA 00
24 OA 5B FB 3E OB AO 03
087A: 0870: 087F: 0882: 0885: 0892: 0894: 08Bl : 08B3: 08C7: 08CB: 080C: 08EA: 08EB: 08EE: 08FO: 08F2: 08F4: 08F6: 08F9:
20 A9 20 20 CC 80 C4 80 AO 80 BC AO 00 20 C9 FO C9 00 20 4C
58 OA 5B 3E C5 80 C9 80 AO 80 02 BC
06 24 14 5B 3E CF C2 00 10 24 3E BI 00 32 C4 A8 00 05 10 03
FB OB CE AE
OB B9
FC CO CO
EE FC FB OB C7 C5 AO 80 C5 C5
OC FO 80 OA 9B F5 58 FC 03 03
08FC: 20 EA 03 08FF: 20 3E OB
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
MENUE WARTEN
WARTEl MENUE I
EINGABE
STA CH LOA #10 JSR TABV JSR PRINT ASC "* SCHNELLER FILE-LESER *" HEX 00 LOA #6 STA CH LOA #20 JSR TABV JSR PRINT ASC "VON OR. JUERGEN" ASC " B. KEHREL" HEX 80 , 00 LOA #16 STA CH JSR PRI NT ASC "( 1986)" HEX 8000 LOX #$32 LOA #$C4 J SR WAI T LOA KBO BPL WARTE l STA STROBE BMI MENUEI OEX BNE WARTEN J SR LOA JSR J SR ASC HEX ASC HEX ASC HEX ASC ASC HEX JSR CMP BEQ CMP BNE JSR JMP
HOME #10 TAB V PRINT "LEGEN SI E 8080 "OIE OI SKETTE MIT OEM TEXTFILE" 8080 IN LAUFWERK I" " 80808080 " = START," " <ESC > ENOE " 00 ROKEY #$80 ;Return OIR #$9B ;Escape EI NGABE HOME OOSCLD
Lies OOS-Catalog OIR
J SR CONNECT J SR PRINT
;OOS anhängen
8. Blitz-Leser 0902 : 0905: 090F : 09 11 : 0914 :
AO C3 8D 20 4C
8D Cl 00 OC 31
195 84 D4 FD 09
0917: 091A: 091D: 0920: 092F :
20 20 87 05 8D
42 3E 87 09 00
FC OB 8D OE
093 1 : 0934: 0938: 093A: 093C: 093F: 0953: 095B: 095D: 095F: 0962: 0965: 0968: 096A: 096C: 096D: 096F:
20 AO A9 85 20 CE 8D A9 85 20 20 20 EO BO 8A DO 4C
3E 8D 05 24 3E Cl AO 3E 33 89 93 6A IF AB
OB 8D
0972 : 0974: 0976: 0979 : 097A:
AO A9 99 88 10
097C: 097D 0980 0982 0985 0986
CA BD 09 9D CA 10
0988 098B 098E
OB CD AO FE FE FD
03 7A 08
ID AO 78 OB FA 00 02 80 78 OB F5
8E F3 OA 20 EA 03 20 42 FC
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
HEX ASC HEX JSR JMP
A08D84 "CATALOG,Dl" 8DOO RDKEY FERTI G ;immer
Textfil e name (Eingabefile ) ZULANG
J SR JSR HEX INV HEX
CLREOP ; Lösche bis PRINT ;Seitenende 87878D ;Piep "EINGABE ZU LANG" 8DO O
FERTIG
JSR HEX LDA STA J SR ASC HEX LDA STA JSR JSR JSR CPX BGE TXA BNE JMP
PRINT A08D8DOO *5 CH PRIN'I' "NAME DES TEXTFILES ?" 8DAOAOAOAOA02DOO U3 E ; Pr ompt-Zeichen PROMPT SETKBD ; DOS abhängen SETVID GETLN ;Ein gabe von ; max. 30 Z *31 ZULANG LESEN MENUEI
;nur Return ;zurück
Tastat ur puffer - ) Fil ename npuffer LESEN LOESCH
COPY
LDY LDA STA DEY BPL DEX LDA ORA STA DEX BPL
*29 UAO FILE , Y
; Fil enamenpuffer ;löschen
LOESCH IN , X U80 FILE,X COPY
;o hn e
All es in Ordnung? Sonst zurück STX VERZUG+l JSR CONNECT JSR CLREOP
auf Maximum setzen DOS anhängen Löschen
9. Blitz-Leser
196 0991 : 0994: 0996: 09A8 : 09B9: 09BA: 09BO: 09BF: 09Cl: 09C3: 09C5 :
20 80 BC AO 00 20 C9 FO C9 00 4C
3E OB 80 02 C5 BC C5 OC FO 80 07 9B F5 7A 08
09C8: 20 EO FO 09CB: 20 EO FO 09CE: 20 EO FO
0901 : 20 E3 03 0904: 84 00 0906: 85 01 0908: 20 OC 03 090B: 84 02 0900 : 85 03
090F: 09El: 09E3: 09E5: 09E7: 09E9: 09 EB: 09EC: 09 EE: 09FO : 09Fl : 09F3:
A9 AO 91 A9 AO 91 C8 A9 91 C8 A9 91
09F5: 09F7: 09F9: 09FA: 09F'B: 09FC: 09FO:
AO 01 Bl 00 4A 4A 4A 4A AO 06
01 00 02 00 07 02 78 02 OB 02
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
REAOKEY
RETURNS
JSR HEX ASC ASC HEX JSR CMP BEQ CMP BNE JMP
PRINT 8080 "
J SR COUT JSR COUT J SR COUT
;3*
Adressen des I/O-Blocks der RWTS und der Parameterliste des Filemanagers holen und eintragen. ROFI LE
JSR GETIOB STY PTRIOB STA PTRIOB+l JSR GETFMPL STY PTRFMPL STA PTRFMPL+l
File mit dem Filemanager öffnen . Parameterliste dafür vorber eiten. Der zu l etzt benutzte DOS-Puffer (vom CATALOG) wird erneut benutzt. LOA LDY STA LOA LOY STA INY LOA STA INY LOA STA
*$01 ;"OPEN" ;Typ des Aufrufs *$00 (PTRFMPL) , Y *$00 ; "Textdatei " *$07 ; Typ des Files ( PTRFMPL ) , Y ;Adresse Filename LO
*
LOY *$01 ;SLOT *16 LOA (PTRIOB),Y LSR LSR LSR LSR ; : 16 ;SLOT LOY *$06
8. Bli tz-Leser
09FF: OAOl: OA03: OA05: OA07: OA09: OAOB: OAOE:
91 AO BI AO 91 A2 20 90
197
02 02 00 05 02 01 D6 03 ID
217 218 219 220 221 222 223 224 225 226 227 228 OAIO : AO OA 229 OA12: BI 02 230 OA14: C9 06 231 OA16 : FO 02 232 OA18 : AO 00 233 OAIA : B9 5F OB 234 OAID: FO 06 235 OAIF : 20 ED FD 236 OA22 : C8 237 OA23: DO F5 238 239 OA25: 20 DD FB 240 OA28 : 84 48 241 OA2A: 4C 66 08 242 243 244 245 246 247 OA2D: AO OE 248 OA2F: BI 02 249 OA31: 85 04 250 OA33: C8 251 OA34: BI 02 252 OA36: 85 05 253 OA38: A9 OC 254 OA3A: 85 06 255 OA3C: AO 08 256 OA3E: A9 00 257 OMO: 91 00 258 OM2: C8 259 OM3: A9 10 260 OM5 : 91 00 261 OM7: A9 00 262 OM9 : AO 03 263 OMB: 91 00 264 OA4D : AO OC 265 OMF : A9 01 266 OA51 : 91 00 267 268 269 270
STA LDY LDA LDY STA LDX JSR BCC
( PTRFMPL) , Y ;DRIVE U02 (PTRIOB), Y ;DRIVE U 05 ( PTRFMPL ) , Y U Ol ;nicht neu einrichten FLEMGR ; File öffnen READ_IT ;kein Fehler
Mögliche Fehler sind "FILE NOT FOUND" und ,, 1/0 ERROR "
IOERR ERRLOOP
TOMENUE
LDY LDA CMP BEQ LDY LDA BEQ JSR INY BNE
UOA ;Fehler-Code ( PTRFMPL) , Y ;F'ILE NOT FOUND U06 ERRLOOP UOO ;sonst 1/0 ERROR ERRTEXT ,Y ;Texte ausgeben TOMENUE COUT ERRLOOP
JSR BELL STY PREG JMP MENUE
; auf Nu ll setzen ;Pause, dann Menü
File erfolgreich geöffnet, jetzt die einzelnen Datensektoren direkt über RWTS in den Puffer lesen. READ_IT
LDY LDA STA INY LDA STA LDA STA LDY LDA STA INY LDA STA LDA LDY STA LDY LDA STA
; TSL-Adresse LO UOE (PTRFMPL),Y PTRTSL ;TSL-Adresse HI (PTRFMPL),Y PTRTSL+l UOC ;Offset in TSL-Liste PTRTRK ;zum erste n Eintrag ; Lesepuffer LO U08 *< PUFFER (PTRI OB), Y ; Lesepuffer HI *> PUFFER (PTRIOB), Y uO O U03 ;VO LUME ( PTRIOB ), Y ; Kommando UOC UO l ; "READ " (PTRIOB), Y
Sektor für Sektor die TS L abarbeiten
198
9. Blitz-Leser
OA53: OA55: OA57 : OA59: OA5B: OA50: OA5F: OA60: OA62: OA64: OA66 : OA69: OA6C:
A4 Bl FO AO 91 A4 C8 Bl AO 91 20 20 BO
06 04 24 04 00 06
OA6E: OA70: OA72: OA73 : OA75 : OA77: OA79: OA7B:
AO Bl 18 69 91 E6 E6 00
09 00
04 05 00 E3 03 09 03 AA
01 00 06 06 06
OA70: AO 09 OA7F: Bl 00 OA81 : 80 01 OB OA84: OA86: OA88: OA8A:
A9 85 A9 85
00 07 10 08
OA8C: OA8E: OA90 : OA92: OA94: OA96: OA98: OA9A: OA9C : OA9E: OAAl : OAA4:
AO Bl FO 09 C9 FO C9 BO 29 20 AO 10
00 07 76 80 80 06 AO 02 lF' EO F'O 00 CO 4C
OAA6: OAA9: OAAB: OAAO: OABO: OAB2:
2C C9 00 4C C9 00
10 CO 9B 03 37 OB AO OA
27 1 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 29 1 292 293 294 295 296 297 298 299 300 30 1 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
REAOLOOP
LOY LOA BEQ LOY STA LOY INY LOA LOY STA JSR JSR BCS
PTRTRK (PTRTSL), Y Track REAOENO kein weiterer Sektor U 04 Track (PTRI OB) , Y PTRTRK ;Sektor (PTRTSL), Y ;Sektor U0 5 (PTRI OB),Y GETIOB RWTS IOERR ; RWTS-Fehler
LOY LOA CLC AOC STA INC INC BNE
; Puffer Hi-Byte U 09 ( PTRIOB ) , Y ;+1 U Ol (PTRIOB ), Y PTRTRK ; Zeiger in der TSL PTRTRK ;we it ersetzen REAOLOOP
Die eingelesenen Sektoren a nzei gen REAOENO
AUSGABEl
AUSGABE2
LEER
LOY U 09 ;Puffer Hi LOA (PTRI OB), Y STA TESTENO+ l ; Endwert "poken " LOA STA LOA STA
* PUFFER PTRPUF+l
LOY LOA BEQ ORA CMP BEQ CMP BGE ANO JSR LOA BPL
*0 (PTRPUF ), Y ZUENOE U80 U 80 AUSGABE2 U AO AUSGABE2 U1 F' COUT KBO VERZUG
BIT CMP BNE JMP CMP BNE
STROBE U 9B LEER AUSGABE4 U AO CR
; Fil e zu End e ;Bit7 setzen ; ? ;Ja, ausgeben ;Control l -Zeichen? ; Nein, ausgebe n ;%000 1 1111 (Inverse ) ; Tastendruck? ;Nein, we iter ;Ja, zurücksetzen ; Escape ? Abbruch Leertaste ? ande re testen
8. Bli tz-Leser OAB4: OAB7: OAB9: OABC:
AD 10 8D 30
00 CO F'B 10 CO 3B
OABE : OACO: OAC2: OAC4 : OAC7 :
C9 DO A9 8D F'O
8D 07 00 F'3 OA 30
OAC9: OACB: OACD: OADO: OAD2 : OAD4: OAD6:
C9 DO AD C9 BO 69 DO
88 15 F'3 OA F'B 04 05 17
OAD8: OADA: OADD: OADF':
84 20 A4 4C
09 DD F'B 09 F'9 OA
OAE2: OAE4: OAE6 : OAE9: OAEB : OAED: OAEF':
C9 DO AD C9 90 E9 8D
95 OC F'3 OA 05 EB 05 F'3 OA
OAF'2: OAF'4: OAF'6: OAF'9: OAF'A :
A9 F'O 20 C8 DO
F'F' 03 A8 F'C 92
OAF'C: OAF'E: OBOO : OB02 :
E6 A5 C9 90
08 08 F'F' 8A
OB04 OB06 OB08 OBOA OBOC OBOE OBI0 OB12 OB14
AO BI F'O AO 91 AO BI AO 91
01 04 25 04 00 02 04 05 00
199 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 . 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
PAUSE
LDA BPL STA BMI
KBD PAUSE STROBE AUSGABE3
CMP BNE LDA STA BEQ
U 8D PF'EIL 11$00 VERZUG+l AUSGABE3
CMP BNE LDA CMP BCS ADC BNE
11$88 SCHNELL VERZUG+l U F'B PIEPS 11$5 POKE
PIEPS
STY JSR LDY JMP
YSAVE BELL YSAVE AUSGABE3
SCHNELL
CMP BNE LDA CMP BCC SBC STA
11$95 VERZUG VERZUG+l 11$5 PIEPS 11$5 VERZUG+l
LDA BEQ JSR INY BNE
U F'F' AUSGABE3 WAIT
INC LDA CMP BLT
PTRPUF'+l PTRPUF'+l U F'F' AUSGABE 1
CR
PF'EIL
POKE VERZUG AUSGABE3
TESTEND
;Pause bis Tastendru ck ; zurücksetzen ;direkt weiter ;
(-
;Verzögerungswert ;+5
;- )
; keine Aktion ; Verzögerung ;we ni gstens noch ;-5
; näc hs tes Zeichen AUSGABE 1 ;Spei c he rseite weite r;sc halten , das Ende tes t en ; Dummy-Wert (wi r d " ge pokt") ;noc h ni cht zu Ende
Prüfe n , ob weit e re TSL ' s da sind
ZUENDE
LDY LDA BEQ LDY STA LDY LDA LDY STA
11$01 (PTRTSL) , Y F'ILEEND 11$04 (PTRIOB) , Y 11$02 (PTRTSL) , Y 11$05 (PTRIOB ) , Y
; Link-Byte Track ; NEIN ; Tr ac k ; Link-Byte Se kt or ;Sektor
200
9. Bli tz-Leser
OB 16: OB18 : OBIA: OBIC: OBIE: OBIF: OB21: OB24 : OB27: OB29: OB2C:
A5 AO 91 A5 C8 91 20 20 BO 4C 4C
04 08 00 05
OB2F: OB32 : OB34: OB37 : OB39: OB3B:
AD 10 2C A9 85 4C
00 CO FB 10 CO 00 48 7A 08
OB3E: OB3F: OB41 : OB42 : OB44 : OB46: OB48 : OB4A: OB4D : OB4E: OB50: OB51: OB52: OB54 : OB56 : OB58: OB5A: OB5B: OB5D: OB5E :
OB5F OB68 OB69 OB77 OB78 OB96
68 85 68 85 AO BI FO 20 C8 00 18 98 65 85 A5 69 48 A5 48 60
00 E3 09 03 20 18
03 03 OA OA
CE CF 01 CE 06 ED F'D F6 CE CE CF 00 CE
09 2F OF 00 06 09 OC 00 AO AO AO 00
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
TOIO ERR FILEEND AUSGABE4
LDA LDY STA LDA INY STA JSR JSR BCS JMP JMP
PTRTSL ;Zieladresse ; Puffer Lo U 08 (PTRIOB), Y PTRTSL+l ; Puffer Hi (PTRIOB), Y GETIOB RWTS TOIOERR READ_IT IOERR
LDA BPL BIT LDA STA JMP
KBD FI LEEND STROBE UOO PREG MENUEI
; au f Null setzen ; zurück
Nach Andy Hertzfeld Call Apple 8/81 PRINT
PRI
ENDE
PLA STA PLA STA LDY LDA BEQ JSR INY BNE CLC TYA ADC STA LDA ADC PHA LDA PHA RTS
PTRPRT
;hole Return;adresse vom ; Stack
PTRPRT+l U
(PTRPRT), Y ;String ENDE COUT ; ausgeben PRI PTRPRT PTRPRT PTRPRT+l *0 PTRPRT
;Stringlänge ;addieren u.
;auf Stack ;zurück , ; dann dorthin ;springen
Feh l ermeldun gen und Puffer für Filenamen ERRTEXT
FI LE
INV HEX INV HEX ASC HEX
"1/0 ERROR" 00 "FILE NOT FOUND " 00 " 00
8. Blitz-Leser
201
Da der schn elle File-Leser ein eigenständiges Programm ist , können wir ihn an den Beginn des Hauptspeichers legen. Hier wäre ab $0800 Platz, aber wenn wir das Byte $0800 im Anschlu ß an den Fi le-Leser nicht wieder auf $00 setzen würden , könnte ein BASIC-Program m nicht ordn ungsgemäß laufe n. Wenn wir erst bei $0803 beginnen, habe n wir solche Probleme ni cht. Die ersten hunde rt Zeilen dürften Ihnen jetzt keine Mü he mehr machen. Es wird ein Titel ged ruckt und ein kleines Menü gestartet. Der CAT ALOG der einliegenden Diskette wird erzeugt , indem wir die Zeichen kette , ,CATALOG über COUT ausgeben. Da DOS in den Datenverkehr einbezogen ist (JSR CONNECT) , wird der Befehl ausgeführt. Wenn sie genau hin scha uen, wird Ihnen hier und in Zei le 124 noch ein AO vor dem 8D des Returns auffallen . Hiermit hat es eine besondere Bewandtnis. Wenn wir bei aktivem DOS die Mon itor-Routine RDKEY ($FDOC) benutzen und anschließend ei n $8D (= Return) über COUT ausgebe n, passiert etwas Merkwürdiges. Das DOS versucht , den Inhalt des Tastaturpuffers als DOS-Befe hl auszuführen, auch wenn ihm kein Ctrl-D voransteht. Meistens steht zu diesem Zeitpunkt auch gar kein Befehl im Tastaturpuffer , sodaß wir schlimmstenfalls abstürzen. Wird erst irge ndein anderes Zeichen außer $84 und $8D über COUT ausgegeben , verhält sich DOS wieder ganz normal. Das Beste ist es, ein fac h ein Leerzeicheen ($AO) zu senden , da dies auf dem Bildsch irm nicht sichtbar ist.
RDKEY $FDOC Zeigt den blinkenden Cursor und holt ein Zeichen über den KSW-Vektor (normal KEYIN $FDIB = Tastatur) E ingabe: A usgabe: Akk u = gelesenes Zeichen
Zum E inlesen des Fi le-Namens benutzen wi r wieder GETLN ($FD6A). Der Na me wird anschließend umkopiert in einen speziellen Zwischenspeicher FILE , den wir zuvor mit Leerzeichen ge löscht haben. Während dieser A ktion wird DOS vo rübergehend abgekoppelt (Zeile 132/133) , damit wir auch File-Name n benutzen können , die gleichzeitig DOS-Befehle sind . Bis zur Zeile 180 passiert dann nichts A ufregendes mehr.
202
9. Blitz-Leser
Mit JSR GETIOB ($03E3) erhalten wir in Y-Register und Akkumulator die Adresse der RWTS-Parameterliste , die hier auch VO-Block genannt wird . JSR GETFMPL besorgt selbiges für den File-Manager. Das Öffnen des Files über den Fi le-Manager kennen Sie schon aus dem vorigen Kapitel, nur daß wir hier ei nige Parameter mehr "von Hand" setzen. Auch das Suchen eines freien File-Puffers ersparen wir uns und nutzen kurzerhand den selben Puffer wieder , der gerade zuvor von CATALOG angelegt wurde. In der Parameterliste des Fi le-Mangers finden wir an der relativen Position $E/F die Lage der TSL im Speicher. Auch hierzu wird ein Zeiger auf der Zero-Page angelegt (PTRTRK), um die Track/Sektor-Paare der RWTS zu übergeben. Alle Sektoren werden in den Speicher gelesen, bis der Fil e zu Ende ist. Bei sehr großen Files können zwei Dinge auftreten. Zum einen kann der Puffer voll sein . Dann wird der Rest des Files in einem weiteren Schub eingelesen. Zum zweiten haben große Fi les mehr als eine TSL. In jeder TSL finden wir an den Positonen $01 und $02 einen Zeiger zur nächsten TSL. Erst wen n derTrackwert $00 ist, haben wir all e TSL's gefu nden. Unser File wird so bis zum letzen Sektor eingelesen.
9.1 Eine kleine DOS-Enzyklopädie Da wir in unseren zwei DOS-Programmen nicht auf alle Möglichkeiten der RWTS und des Fi le-Managers eingehen konnten , werden jetzt tabell arisch die Besonderheiten dieser beiden Unterprogramme vorgeste llt. Die Parameter-Liste der RWTS (lOB) ist wie fol gt aufgebaut : Byte Byte Byte Byte Byte Byte Byte Byte Byte Byte Byte Byte Byte Byte Byte
$00 $0 1 $02 $03 $04 $05 $06 $07 $08 $09 $OA $OB $OC $OD $OE
01 60 01 00 04 OF Lo Hi Lo Hi 00 00 02 00 00
Konstante jetziger Slot * 16 (hier Slot 6) jetziges Laufwerk (1 oder 2) erwartete Volurne-Nurnrner ($00 paßt für al l es) gewünschter Track ($00-$22 , hier $04) gewünschter Sektor ($OO-$OF , hier $O F) Lo-Byte der DCT (s.u.) Hi-Byte der DCT Lo-Byte des Datenpuffers (256 Bytes) Hi-Byte des Datenpuffers Konstante Konstante Befehlsbyte (s.u.) Feh l ercode, wird vorn DOS gepoked alte Volurne-Nurnrner
9.1 Eine kleine DOS-Enzyk lopädie
Byte $OF Byte $10
60 01
203
l etzter benutzter Slot (hier Slot 6) l etztes benutztes Laufwerk
A lle Bytes verstehen sich relativ zum Beginn , dessen absolute Adresse Sie durch ein JSR GETIOB erhalten (Y-Reg = Lo , Akku = Hi). Die Bytes $06 und $07 e nthalten einen Zeiger auf eine weitere Tabelle, die D CT (Device Characteristics Table). Für ein DISK lI-La ufwerk hat sie immer das folgende Aussehen:
Byte Byte Byte Byte
$00 $01 $02 $03
($ 11 ) ($12) ($ 13) ($14)
00 01 EF 08
Konstante Konstante Konstante Konstante
(Laufwerkstyp) (Phasen per Track - i ) (Anl aufzäh l er) (An l aufzähler)
Da die DCT zumeist direkt hinter dem IOB li egt, si nd in Klamm ern die Bytes weitergezählt. Das Byte $OC enth ält eine n der fo lgenden Befehle: $00 Seek = nur Track/Sektor suchen (Kopfbewegung) $01 Read = bezeichnete n Sektor lese n $02 Write = bezeichneten Sektor schreiben $04 Init = Diskette ganz initialisieren (ohne HELLO-Programm) Bevor Sie die Codes $02 und $04 a usprobi e re n, sollte n Sie sicher sein , daß Ihr Programm auch funkti o niert! Wenn Sie den IOB des DOS mitbe nutzen , müssen Sie die Bytes $06/07, $OD bis $10 sowie die DCT nicht selber initialisieren. Schreiben Sie dagegen eine n eigenen lOB , müssen alle Bytes gesetzt we rde n. Damit die RWTS weiß , welcher lOB be nutzt werden soll , ist beim RWTS- A ufruf die IOB -Adresse in Y-Register (Lo) und Akkummulator (Hi) zu überge be n. Im Normalfa ll geschi eht das so:
J SR GETIOB JSR RWTS DOS-Tabelle nutzen
LDY #< !OB ; Lo-Byte LDA #> !OB ; Hi -Byte J SR RWTS eigene Tabelle nutzen
Wenn nach de m JSR RWTS das Ca rry-Bit gesetzt ist , trat ein Fe hle r a uf, dessen Code im relativen Byte $OD zu finden ist. Die RWTS verwe ndet inte rn di e Speicherstell e $0048, die gleichzeitig auch vo m Mon ito r benutzt wird. D amit es hi er nicht zu Konfli kten kommt, können wir $0048 nach jedem JSR RWTS auf $00 setzen. Der Fi le-Manager besitzt noch me hr Befeh le als die RWTS . Fo lglich fällt a uch die Paramete rliste komplizie rter aus. Sie müssen allerdin gs nicht imme r alle
Be fehl : Byte $00 Byte $01 Byte $02 Byte $03 Byte $04 Byte $05 Byte $06 Byt e $07 Byte $08 Byte $09 Byte $OA Byte $OB Byte $OC Byte $OD Byte $O E Byte $OF' Byte $10 Byt e $11 Vo l. Dry. Dry. Sl ot Sl ot
DEL . CAT. 05 06
POS. INIT VERIF'Y OA OB OC DOS-P neuer Rec. Name num. Vol. Vol. Vol. Rec. Vol. Vol. Drv . Dry. Dry. off. Dry. Drv. Sl ot Sl ot Sl ot Sl ot Slot LOCK UNL. REN. 07 08 09
Adresse des Name Name F'ilenamens adr. ad r . der Aus f ü h run g n ach unbenutzt Lo- Byte der Adresse des F'ile-Manager-Arbeitsbereichs (45 Byte) Hi- Byte der Adresse des F'ile- Manager- Arbeitsbereichs TSL-Lo Lo-Byte des TSL-Puffers TSL-Puffer Lo TSL-Hi Hi - By t e des TSL-Puffers TSL- Puffer Hi DatenDa t en-Puffer Lo Puffer Da t en- Puffer Hi
OPEN CLOSE READ WRITE 01 02 03 04 Untergruppe RecordRec. länge nummer RecordVol. Dry. offset PufferSlot Typ l ä nge Byte oder Name adr. Pufferadr. F' e h 1 e r c 0 d e
~
(1l
C
z
a.
:::i
::::I:JCI
-
(1l
0
0
0
_.
,....,.
,....
§ ::;
:::i
c,
"""'
~
~,
C'O
1» =
:::s
Cl.
-:
(t>
(1)
,....,.
_ .
o..
:::i
::l
(D
(j)
c;n
~;;l l::1:l tT1(1l(JQ'<
:J
-.:J:::i
::r'
...... '"
::> ~
:::i
(1l;;l ~ ~ ;l> (JQ ::r- ~ _ . ciQ' (1l (1l a. (1l =: ::> ::>
3_ '
:::i
::r-;:::;!2. ü a. CI(1l ~ (1l C ~ I» 0 ::;
fl
~, ~
~ ::>
g , ~ 3 ;:; ~ &.
cn CI - , (1l ::r(ij ' 0 ~ (; g cn 1» ""
e~g-("D§:; :::i(ö :j ..,.~'"d(1l cn ::> ::; 00 cn ~ ..., (ij ' C ..... ~ ''''
;...g .~ e, '"d~~
=rr en
o
cn
~ ~ ~. :::i ~ ::r _ . ~ :J A ,..., 0 cn (1l 0' I»
ct~
C/1
B- '""d'-"~(D
:J
0 3 ()q (1l _ . (1l ::> 0'""d ,....,. ~ .
(ij' (ij ' ~ .
cn CI ~
~>-<:a 3 C1 Ml C ~ -5 1::1:ltT1(; ~ ::> 3 -, _ . '"d >-l ::> ::r~ 5: CD c t:C '""d :::. 1»' cb ;;; ::> C C Ü ~ 5 ° ' 0. ~ ~ ~ . (1l ::> ClO'V> ...,::> ::> ;:; . ~ 3:: ;l> :5.. a. PO ;:r Z '"d ~ @ 5 ' c
(b (;"
-
::; .
::> ~. g ~ (1l ..., g ::E.
~ ::>::>
C cn
o·
~
~
(;
Ml ~ ;;l ::> ::r- '"d::E()q ::>
~
(JQ
3 3 ~>-<:gg ~ r- . ,......,. 7j :::i . Po)
:j
NI»'
~ '"(1lÜ (1l ...,
~
rJ'l
g
g W ~ . fJ 5' eil" ....,.
:::i
3 ..., S. "8. 0
(JQ
0
'"d'"d ...,
I»
...,
I»
'"...,(1l
r-.(1l
N
l::1:l
\0
~
9.1 E ine klein e DOS-E nzyk lopädie
205
Da der Platz in der Tabelle beschränkt ist, besprechen wir einige Position en genauer. Für all e Befehle gilt , daß in Position 0 der Befehl scode und an Position C/D ein Zeiger (Lo/Hi) auf den Arbeitsbereich vo n 45 Bytes für de n File-Manager angege ben werden müssen. Positi on A e nthält nac h der A usführung den Feh lercode . Bei ein em Fehler ist zusätzlich das Carry-Bit gesetzt. Mögliche Fehler sind: $00 - kein Fehler (keine eigentliche Meldung) $01 - Sprache nicht vorhanden (LANGUAGE NOT A VAILABLE) $02 - ungültiger Befehlscode $03 - ungültige U ntergruppe bei R EAD und WRITE $04 - Diskette schre ibgeschützt (WRITE PROTECTED) $05 - Fileende erreicht (EOF) $06 - Fi le ni cht gefunden (FILE NOT FOUND) $07 - fa lsche Vo lume-N ummer (VOLUME MISMATCH) $08 - 1/0 Feh ler allgemein (IIO ERROR) $09 - D iskette voll (DISK FULL) $OA - File gesperrt (FILE LOCKED)
OPEN öffnet eine Datei. Slot, La ufwe rk und Vo lume-Nummer ($00
= alle)
müsse n überge ben werden . Positio n 7 enth ält den Typ des Files : $00 - Textfi le $01 - Integer-BASIC Programm $02 - Applesoft-BA SIC Programm $04 - Binärfile $08 - Typ S $10 - Typ R(elokatibe l) $20 - Typ A $40 - Typ B Ist B it 7 zusätzlich gesetzt, ist der Fi le "gelockt". Position 8 und 9 enthalten einen Zeiger (Lo/Hi) auf den Filenamen, die Positionen E und F einen Zeiger (Lo/H i) zum TSL-Puffer. Wollen Sie einen R andom- Access-Textfil e öffnen, muß in den Position en 2 und 3 die Recordlänge eingetragen werden , ansonste n ein $0000 . Open richtet einen File-Puffer ein und liest den (ersten) TSL-Sektor. In Position 7 wird der tatsächlich gefundene Filetyp abgelegt. Wurde der File nicht gefunden, hängt di e Reaktion vo m X-Register ab. Wa r das X-Register beim Aufruf des File-Managers Null ($00), wird ein File angelegt, ansonste n erfo lgt die Fehlermeldung " FILE NOT FOUND " .
206
9. Blitz-Leser
CLOSE schließt einen File, indem der letzte Datensektor aus dem Puffer auf die Disktte geschrieben wird sowie VTOC (VOLUME TABLE OF CONTENTS = Diskettenbelegung) und TSL aktualisiert werden. Der File-Puffer wird allerdings nicht freigegeben.
READ und WRITE unterscheiden sich nur im Befehlscode in Position O. Sie lesen oder schreiben ein einzelnes Byte oder eine Gruppe von Bytes von bzw. auf Diskette. Zur näheren Spezifizierung muß eine Untergruppe in Position 1 definiert sein: $00 - keine Funktion ausführen $01 - nur 1 Byte lesen/schreiben. Es wird dieaugenblickliche Position im File benutzt, das Datenbyte wird nach bzw. aus Position 8 transportiert. $02 - mehrere Bytes lesen/schreiben ab der augenblicklichen Fileposition . In Position 8 und 9 muß die Anfangsadresse der Daten stehen , in Position 6 und 7 die Zahl der Bytes. Beim Schreiben (WRITE) muß diese Zahl um Eins (1) zu klein angegeben werden. $03 - erst positionieren, dann wie $01. An den Parameter-Positionen 2/3 muß die Recordnummer , an 4/5 der Recordoffset angegeben werden (siehe auch POSITION). $04 - erst positionieren, dann wie $02 . An den Parameter-Positionen 2/3 muß die Recordnummer, an 4/5 der Recordoffset angegeben werden (siehe auch POSITION). Bei allen Untergruppen wird der Zeiger auf die Fileposition hinter das zuletzt gelesene/geschriebene Byte gesetzt und an den Positionen 2-5 angezeigt. Vor READ/WRITE ist der File mit OPEN zu öffnen.
DELETE markiert im Catalog der Diskette einen File als gelöscht . DELETE führt selbst ein OPEN durch. Bis auf den Befehlscode sind alle Parameter wie bei OPEN. Setzen sie das X-Register vor dem Aufruf auf $00.
CATALOG gibt den Catalog der Diskette auf der aktiven Ausgabeeinheit (zumeist Bildschirm) aus. Außer Slot und Laufwerk ist nur wie immer die Adresse des Arbeitsbereichs an Position C/D anzugebe n.
LOCK und UNLOCK setzen bzw. löschen das Bit 7 des Filetyps im Cata log der Diskette. Da auch hier ein automatisches OPEN erfolgt, sollte das X-Register gleich Null sein. A lle Parameter entsprechen dem OPEN-Befehl. RE NAME benennt einen File um. Während in der Parameterliste die Positionen 8/9 auf den alten Namen zeigen, muß in Position 2/3 ein Zeiger (Lo/Hi) auf
9.1 Eine kleine DOS-Enzyklopädie
207
den neuen Namen stehen. Da auch hier ein OPEN durchgeführt wird, sind die übrigen Parameter wieder identisch wie bei OPEN. POSITION stellt den Datenzeiger auf eine beliebige Position im mit OPEN geöffneten File. Vor dem ersten READ oder WRITE ist immer ein POSITION erforderlich , wenn nicht die Untergruppen $03 oder $04 benutzt werden. Die Position wird bestimmt, indem die gewünschte Recordnummer (Position 2/3) mit der Recordlänge (aus dem OPEN) multipliziert wird. Für eine Position innerhalb eines Records kann zusätzlich ein Offset (Position 4/5) zum Recordbeginn angegeben werden. Der Datenzeiger wird auf das erste Byte im File gesetzt , indem an den Positionen 2- 5 jeweils eine $00 eingetragen wird . INIT formatiert eine ganze Diskette, legt einen leeren Catalog und eine Belegungsli ste (VTOC) an und schreibt ein Abbi ld des DOS auf die Spuren 0- 2. An den Positionen 4-6 sind Volume-Nummer, Slot und Laufwerk anzugeben , an Position 2 zusätzlich das Hi-Byte der ersten DOS-Speicherseite (normal
$9D). VERIFY liest einen File komplett über die RWTS , ohne ihn permanent abzuspeichern. Auf diese Weise wird seine Lesbarkeit überprüft. D ie Parameter entsprechen dem OPEN , da dieses automatisch miterfolgt.
208
10. Mehr PRO als CONTRA Mit der Einführung von ProDOS hat die Firma Apple für den Assembler-Programmierer eine völlig neue Betriebssystem-Umgebung geschaffen, die ein radikales Umdenken im Vergleich zum alten DOS 3.3 mit sich bringt. Beim DOS 3.3 gab es - mit der Ausnahme einiger Vektoren auf der Se ite 3 - keine definierte Schnittstelle zwischen Assembl er-Programmen und dem DOS. Da DOS 3.3 aber über viele Jahre konstant blieb, konnte der Programmierer direkt in verschi edene Routin en wie z.B die RWTS oder den Fi le-Manager hineinspringen und sicher sein , daß all es funktionierte. ProDOS ist dagegen nicht adressenkonstant. Bis heute si nd wenigstens 4 offizielle Versionen (1.0 , 1.0.1, 1.0.2, 1.1.1) auf dem Markt, die sich alle durch mehr oder minder große Verschiebungen auszeichnen. Die Entwickler von ProDOS haben aber für Abhilfe gesorgt , indem sie eine genau definierte und konstante Schnittstelle in das ProDOS einbauten, das Machine Language Interface (MLI, Maschinensprache-Schnittstelle) .
10.1 Gute Kontakte per Schnittstelle Alle direkten Aufrufe des ProDOS sollten über die genormte MLI-Schnittstelle erfolgen. Die Firma Apple hat im "Technical Reference Manual " einen MLIAufruf wie folgt definiert: JSR HEX ADR BEQ FEHL
$BFOO COMMAND PARMBLOCK KEINFEHL
alleinige Einsprungad re sse MLI Funktionscode Adresse de s Parameterbl ocks Ca r ry-Flag =0 / Z-Fl a g = 1 , wenn kein Fehler Feh l erbehandlung, Fehlercode im Akkumulator
PARMBLO CK HEX PARMCOUNT ; Pa rameter-Anzahl HEX PARMl ; 1 . Parame ter (1 Byte )
10.1 G ute Kontakte per Sch nittstelle
ADR HEX
PARM2
209
2. Parameter (2 Bytes) N. Par ameter
Der PARMBLOCK kann irgendwo im Speicher stehen. Das erste Byte steht für die Anzahl der Parameter , die nicht mit der A nzahl der benutzten Bytes identisch sein muß , denn ein Parameter kann auch zwei oder drei Bytes umfassen. Der Aufruf des MLI muß stets mit einem JSR MLI erfo lgen. ProDOS schiebt intern die Rücksprungadresse weiter, sodaß der Rücksprung immer hinter die Adresse des Parameterblocks erfolgt. Für COMMAND ist ein Byte für de n aufgerufenen Befehl einzusetzen , das Sie der fo lgenden A ufste ll ung entn ehmen kö nnen. Die beiden folgenden Bytes zeigen im Lo-Hi-Fo rm at auf den jeweiligen P ARMBLOCK für diesen Aufruf. MLI-intern wird zue rst das COMMAND überprüft. Bei einem nicht definierten COMMAND fo lgt ERR 01: BAD SYSTEM CALL NUMBER . Danach wird die A nza hl der Parameter (P ARMCOUNT) geprüft. Bei Nichtübereinstimmung fo lgt ERR 04: BAD SYSTEM CALL PARAMETER COUNT. Ganz allgemein wird ein Ausführu ngsfehler dad urch angezeigt , daß das Carry-B it gesetzt und die Zero-Flag gelöscht ist. Der Akku mulator enthält die Fehlernummer. Ei ne Fehlerbehandlungs-Routine müssen Sie selber schreiben. X- und Y-Register bleiben bei jedem MLI-Aufruf erhalten, da sie zwischenges peichert werden. Die folgende Aufstellu ng enthält alle zur Zeit gü ltigen MLI-Aufrufe und gibt die Zahl und den A ufbau des Parameterb locks an. Als Namen wurden die vo n Apple eingeführten Bezeichnungen ve rwendet.
$40: ALLOCATE INTERRUPT
PARMCOUNT = 2 Referenz-Nummer - 1 Byte Service-Start - 2 Byte-Adr esse ProDOS kann bis zu vier Interrupt-Routinen verwa lte n, die von Ihnen geschriebe n und über diesen Aufruf dem ProDOS angemeldet we rden müssen. Der Service-Start wird auf den nächsten fre ien Platz der INTERRUPT T ABLE ei ngetrage n, die Referenz-Nummer im Bereich 1-4 wird zurückgeliefert. Fehler: E RR 25: INTERRUPT TABLE FULL (wenn bereits alle vier möglichen Startad ressen belegt wurde n) sowie ERR 53: INVALID SYSTEM CALL PARAMETER (Startadresse kleiner als $0100).
10. Mehr PRO als CONTRA
210 $41: DEALLOCATE INTERRUPT
PARMCOUNT = 1 Referenz-Nummer - 1 Byte
In der INTERRUPT TABLE wird die Startadresse der bezeichneten InterruptRoutine gelöscht. Fehler: ERR 43: INVALID REFERENCE NUMBER (Referenz-Nummer nicht im Bereich 1-4).
$65: REBOOT (= QUIT) PARMCOUNT
=
4
Die Routine REB OOT wird aus der Language Ca rd kopiert und ausgeführt. Dieses COMMAND ist nachträglich eingebaut wo rden. Die vier Parameter für dieses COMMAND sind "unecht" . Sie sollten 6 mal $00 benutzen (2 Zweierund 2 Einergruppen). REB OOT erkärt den ganze n Speicher als unbelegt und frag t den Benutzer nach dem Namen ein es System-Programms. Dieses wird anschließend geladen und gestartet.
$80: READ BLOCK PARMCOUNT = 3 Unitnummer - 1 Byt e (DSSS 0000 ) Zie l puffer - 2 Byte-Adresse Bl ocknummer - 2 Bytes
Liest einen Block (= 2 Sek toren) vo n einem externen Datenspeicher ab "Zielpuffe r" in den Speicher. Vo r dem Aufruf wird überprüft, ob der Zielbereich als frei deklariert ist. Bei Zieladressen, die größer als $BFFF sind , ergibt diese r Test Unsinn . Bei der Unitnummer ist in Bit 7 die La ufwer ksnummer D (0 = Laufwe rk 1, 1 = Laufwerk 2) und in den Bits 4-6 die Slotnummer S (1-7) anzuge ben. S6 ,Dl => %0110 0000 = $60 Fehler ERR 56: BAD BUFFER ADDRESS (Zielgeb iet belegt), ER R 28: NO DEVICE CONNECTED (U nitnummer eines nicht existi erenden Datenspeichers) sowie ERR 27 : VO ERRO R.
10.1 Gute Ko ntak te per Schnittste ll e
211
$81: WRITE BLOCK
PARMCOUNT = 3 Unitnummer - 1 Byte (DSSS 0000) Quellpuffer - 2 Byte-Adresse Blocknummer - 2 Bytes Der entsprechende Block mit dem Speicherin halt ab "Quellpuffer" wird auf den angesprochenen Datenspeicher geschrieben . Bei der U nitnummer ist in B it 7 die Laufwerksnummer D (0 = Laufwerk 1, 1 = Laufwerk 2) und in den Bits 4-6 die Siotnummer S (1-7) anzugeben . S6 ,D2 ~ % 11100000 = $EO Fehler wie bei READ BLOCK , nur kom mt noch ERR 2B: DISK WRITE PROTECTED hinzu.
$82: GET TIME
PARMCOUNT
=
0
Dieses COMMAND wurde nachträglich "eingeflickt" und bewirkt einen Aufruf von $BF06 - hier sollte dann ein Sprung zur Uhrenro utine (Standard : $F142) ste hen . Die offizielle Uhr hat folgende A usgabe: $BF90/91: Lo/Hi von JJJJJJJM MMMlTTTT. J = Jahr nach 1900 , M = Monat (1-12) , T = Tag (1 -31). $BF92/93: Lo/H i von SSSSSSSS MMMMMMMM . S = Stunde , M = Min ute Fe hler: keine .
$CO: CREATE
PARMCOUNT = 7 Path-Name - 2 Byte-Adresse Acces s - 1 Byte File-Type - 1 Byte Aux-Type - 2 Bytes Storage-Type - 1 Byte Creation Dat e - 2 Bytes Creation Time - 2 Bytes Mit di esem COMMAND werden Daten- oeler D irectory-Files e rstellt. Soll eine bereits ex istiere nde Datei ne u angelegt werden, muß sie erst mit $Cl DESTROY gelöscht werden. Access enthält ei ne B itmaske mit fo lgender Bedeutung: Bit 7 gesetzt , wenn Datei gelöscht werden ka nn
212
10. Mehr PRO als CONTRA
Bit 6 gesetzt , wenn Bit 5 gesetzt , wenn Bit 4-2 ungenutzt Bit 1 gesetzt , wenn Bit 0 gesetzt , wenn CREATE setzt Bit
Datei umbenannt werden kann Datei Back-Up benötigt auf Datei geschrieben werden kann von Datei gelesen werden kann. 5 automatisch.
Fi le-Type umfaßt folgende Haupt-Filetypen : Typ
Name
Bedeutung
$00 $01 $04 $06 $OF $19 $lA $1B $EF $FO $F1 $FA $FB $FC $FD $FE $FF
BAD TXT BIN DIR ADB AWP ASP PAS CMD bis $F8 INT IVR BAS VAR REL SYS
ohne Typ Datei mit Fehlerb lock ASCII-Textdatei mit Bit 7 = 0 Binärfile Subdirectory Appleworks Datenbank Appleworks Textverarbeitung Appleworks Tabellenkalkulation ProDOS PASCAL Befehls-Datei Benutzerdefiniert Integer BASIC File (?) Integer BASIC Variablen (?) Applesoft BASIC File Applesoft BASIC Variablen relokatives Assemblermodu l von EDASM System-File
Aux-Type enthält je nach File-Type unterschiedliche Angaben: für TXT die Record-Länge (Lo/Hi) , für BIN, BAS, VAR und SYS die Lade-Adresse (Lo/Hi). Ansonsten wird diese Information nicht benötigt. Der Parameter " Path-Name" enthält die Adresse , auf der der Pathname selber in ASCII mit vorangestelltem Längenbyte stehen muß. Der letzte Name im angegebenen Path ist der Name des zukünftigen Fi les.
213
10.1 Gute Kontakte per Schnittstelle
Die Unterscheidung zwischen "Datenfile" und "Subdirectory" hä ngt nur vom angegebenen Storage Type ab: für $OD wird ein Subdirectory Key Block erstell t, für 0/1/2/3 wird ein Datenfi le erstellt, der immer den Storage Type 1 (Säm ling) hat. We nn DATE un d TIME angegeben sind 00) , werden die Werte aus dem Parameterb lock benutzt, ansonsten wird die System-Zeit eingesetzt. Fehler: ERR: 27 IIO ERROR , ERR: 2B WRITE PROTECTED , ERR 40: INVALID PATHNAME , ERR 44/45 : DIRECTORYIVOLUME NOT FOUND, ERR 47 : DUPLICATE FILENAME , ERR 48: VOLUME FULL, ERR 49: VOLUME DIRECTORY FULL, ERR 4B : UNSUPPORTED STORAGE TYPE (für CREATE mit Storage Types <> 0/1/2/3/$D) , ERR: 5A FILE STRUCTURE DAMAGED (BIT-MAP defekt) .
«>
$Cl: DESTROY PARMCOUNT = 1 Path-Name - 2 Byte-Adres s e
Der File, auf dessen Namen "Path-Name" zeigt (siehe CREATE) , wird aus dem Directory entfernt, die zum Fil e gehörigen Blocks werde n wieder freigegeben. DESTROY ist ni cht möglich , we nn a) der Fi le OPEN ist , b) im Access-Byte des File-Eintrags Bit 7 nicht gesetzt ist , c) der Fil e ei n Subdirectory ist , das seinerseits noch weitere File-E in träge enthält. In diesen Fällen fo lgt ERR 4E: FILE ACCESS ERROR, ERR 50: FILE IS OPEN Weitere Feh ler: ERR: 27 IIO ERROR , ERR: 2B WRITE PROTECTED, ERR: 40 INVALID PATHNAME , ERR: 44 DIRCTORY NOT FOUND , ERR: 45VOLUMENOTFOUND , ERR: 46FILENOTFOUND , ERR: 4A INCOMPATIBLE FILE FORMAT
$C2: RENAME PARMCOUNT = 2 Path-Name - 2 Byte-Adresse Neuer Path-Name - 2 Byte-Adre sse
RENAME ist für Volumes , Subdirectories und Datenfi les möglich. Zur Definition der Path-Namen siehe unter CREATE.
214
10 . Mehr PRO als CONTRA
Der Unterschied zwischen neuem und alte m Path muß im letzten Na mensteil beider Paths auftrete n, ansonsten fo lgt ERR 40: INVALID PATH NAME. A lle anderen Namenstei le der Pat hs müssen gleich sein. Für Volumes ist RENAME nur möglich, we nn auf de m Volum e kein File (auch das Di rectory selber) OPEN ist , ansonsten fo lgt ERR 50: FILE IS O PEN . Für Subdi recto rieslDatenfiles wird zusätzli ch geprüft, ob der Access des Files das entsprechende Bit (B it 6) gesetzt hat. Ist das nicht der Fall , fo lgt E RR 4E: FILE ACCESS ERR OR. Existiert bereits ein File mi t de m neuen Namen, fo lgt ERR 47: DUPLICATE FILENAME. Weitere Fehl er: E RR: 27 1/0 ERROR, ERR: 2B WRITE PROTECTED , ERR: 40 INVALID PATHNAME , ERR: 44 DIRCTORY NOT FOUND , E RR: 45VOLUMENOTFOUND,ERR: 46FILENOTFOUND , ERR: 4A INCOMPATIBLE FILE FORMAT, ERR: 4B UNSUPPORTED STOR AGE TYPE, ERR : 57 DUPLICATE VOLUME
$C3: SET FILE INFO
PARMCOUNT = 7 Pat h-Name - 2 Byte- Adresse Access - 1 Byte File-Type - 1 Byte Aux-Type - 2 Bytes Nu ll - Fe l d - 3 Bytes Modification Date - 2 Bytes Modification Time - 2 Bytes Dieses COMMAND verä nd ert die Attribute (Eigenschaften) eines Files. SET FILE INFO ka nn fü r Volume Directories nicht angewandt we rden ; ERR 40: INVALID PATHNAME . Mit diesem COMMAND kann z ..8. der Access ein es Files neu gesetzt we rden, da das Sperren eines Files gegen e in SET FILE INFO ni cht möglich ist . Z u Path-Name , Access, File-Type , A ux-Type siehe unter CREATE. Das Null-Fe ld ka nn beli ebige We rte ann ehmen. Es existiert lediglich , um für di e ersten 7 Parameter dasselbe Format des P ARMBLOCK wie für GET FILE INFO zu erh alte n. Wenn DATE und TIME spezifiziert sind, werden diese Angaben benutzt , anso nsten wird die System-Zeit eingesetzt. Fehler: ERR: 27 IIO ERROR , ERR: 2B WRITE PROTECTED , ERR 40: INVALID PATHNAME , E RR 44/45/46 : DIRECTORY/vOLUME/FILE NOT FOUND , E RR: 4A INCOMPATIBLE FILE FORMAT, ERR : 4B
10 .1 Gute Ko nta kte per Schnittstelle
215
UNSUPPORTED STORAGE TYPE, ERR: 4E FILE ACCESS ERROR, ERR: 5A FILE STRUCTURE DAMAGED (BIT-MAP defekt).
$C4: GET FILE INFO PARMCOUNT = $OA (10) Path-Name - 2 Byte-Adresse Access - 1 Byte-Resultat File-Type - 1 Byte-Resultat Aux-Type - 2 Byte-Resultat / TOTAL BLOCKS Storage-Type - 1 Byte-Resultat BLOCKS US ED - 2 Byte-Resultat / TOTAL BLOCKS USED Modification Date - 2 Byte-Resultat Modification Time - 2 Byte-Resulta t Create Date - 2-Byte Resultat Create Time - 2-Byte Resultat Dieses COMMAND stell t das Gegenstück zu SET FILE INFO da r. Es li est die Attribu te ein er Datei in die Parameterliste ein . Von Ihnen mu ß led iglich PARMCOUNT und der Zeiger auf den Path-Namen gesetzt sowie da hinter de r benötigte Platz freigehalte n we rde n. Für SubdirectorieslDatenfi les enthä lt der A ux-Type de n A ux-Type und BLOCKS USED gibt die A nzahl der vom Fil e be legte n Blocks an. Dem Null-Fe ld vo n SET FILE INFO entsprechen hier Storage-Type und BLOCKS USED. D iese beide n Parameter sind mit SET FILE INFO nicht verände rbar. Für Vo lume Directories wi rd anstell e des A ux-Type die Gesa mtkapazität des Volum es (TOTAL BLOCKS) und für BLOCKS USED die Gesamtza hl de r auf dem Vo lume belegten Blocks (TOTAL BLOCKS USED) zurückgeli efert. Z u den Defini tionen de r Para meter siehe CREATE. Für Storage-Type gilt: $0 = gelöschter Fi le $1 = Seedling (Sä mling) mit max. 1 Datenblock $2 = Sapling (Schöß li ng) mit einem Indexblock $3 = T ree (Ba um) mi t einem Maste rb lock $D = Subdirectory Fehler: E RR: 271/0 ERROR , ERR 40: INVALID PATHNAME , ERR 441 45/46: DIRECTO RYNOLUME/FILE NOT FOUND , ERR: 4A INCOMPATIBLE FILE FORMAT, ERR : 4B UNSUPPORTED STORAGE TYPE , E RR : 5A FILE ST RUCTURE DAMAGED (B IT-MAP defekt).
216
10. Mehr PRO als CONTRA
$C5: ON LINE
PARMCOUNT = 2 Unitnummer - 1 Byte (DSSS 0000) oder $00 ("Alle " ) Zielpuffer - 2 Byte- Adresse ON LINE schreibt den Volume-Namen der/des adressierten U nits (U nitnummer siehe READ BLOCK) ab der Adresse "Zielpuffer " in den Speicher. Wenn die Unitnummer mit $00 angegeben ist , werden sämtliche Units aus der DEVICE T ABLE bearbeitet. Bei einer spezifizierten Unitnummer $00) müssen $10 , ansonsten $100 Bytes bereitgestellt werden . Ist der entsprechende Speicherbereich als belegt deklariert , fo lgt ERR 56: BAD BUFFER ADDRESS. Pro U nit werden 16 Byte ausgegeben: O. Byte: DSSSNNNN (D = Drive , S = Slot, N = Länge Volume-Name 1. -15. Byte: Fehlercode oder Volume-Name ohne Schrägstrich Bei ERR: 57 enthält Byte 3 die Nummer des anderen Units mit gleichem Volume-Namen. Das E nde der E inträge ist durch $00 in Byte 0 und 1 gekennzeich net.
«>
Fehler: ERR: 28 NO DEVICE CONNECTED, ERR : 2E DISK SWITCHED AND FILE OPEN , ERR: 45 VOLUME NOT FOUND , ERR 52: NOT A PRODOS VOLUME, ERR 57: DUPLICATE VOLUME (wenn zwei Volumes den selben Namen haben und auf mindestens einem der beiden Volumes ein File OPEN ist).
$C6: SET PREFIX
PARMCOUNT = 1 Path-Name - 2 Byte-Adresse Dieses COMMAND setzt ein PREFIX und sucht das entsprechende Vo lume bzw. die entsprechende Subdirectory. Path-Name siehe CREATE. Ist das erste Zeichen ei n "I", so wird das alte Prefix ersetzt, ansonsten wird der neue Path-Name an das alte Prefix zu einem neuen Prefix angehängt. SET PREFIX ist auch mit einer Länge vo n $00 möglich , d.h. der Pathname besteht nur aus einem "I" . In diesem Fall wird das PREFIX gelöscht. Feh ler: ERR 40: INY ALID PATHNAME ("letztes File im Path-Name ist kei n Subdirectory" oder " Gesamt-Prefix länger als $40 Zeichen"), ERR: 44/45/46 DIRECTORYIVOLUMEIFILE NOTFOUND , ERR: 4A INCOMPATIBLE
10.1 G ute Kontakte per Schni ttstelle
217
FILE FORMAT, ERR: 4B UNSUPPORTED STORAGE TYPE, ERR: 5A FILE STRUCTURE DAMAGED (BIT-MAP defekt).
$C7: GET PREFIX PARMCOUNT = 1 Zi e lpuffer - 2 Byte-Adresse Das PREFIX wird in den Zielpuffer ($40 Bytes Platzbedarf) kopiert (beginnend mit Längenbyte und ein letzte r "I" angehängt). Ist kein PREFIX gesetzt , fo lgt Rücksprung ohne Feh le r. Fehler: ERR 56 : BAD BUFFER ADDRESS.
$C8: OPEN PARMCOUNT = 3 Pat h-Name - 2 Byte-Adresse Filepuffer - 2 Byte-Adresse Referenz-Nummer - 1 Byte Resultat OPEN sucht ein e Datei und reserviert für sie einen IIO-Puffer. Der Fi le muß bereits existieren , ansonsten folgt ERR 46: FILE NOT FOUND. In der System Bit Map wird der Filepuffer mi t einem Platzbedarf von $400 Bytes ab der angegebenen Startadresse (Lo-Byte muß $00 sein !!) geprüft und belegt. Ist der entsprechende Platz nicht frei , fo lgt ERR 56: BAD BUFFER ADDRESS. Die Referenz-Numme r (1-8) wird in den Parameterblock eingetrage n. Über diese Nummer finden alle zuk ünftigen Aktion en mit diesem File statt. Sie muß deshalb vom Programm zwischengespeichert werden. Es können maxim al 8 Files gleichzeitig geöffnet sein. Fehler: ERR: 27 IIO ERROR , ERR 40: INVALID PATHNAME , E RR: 42 MAXIMUM NUMBER OF FILES OPEN , ERR 44/45/46 : DIRECTORYI VOLUME/FILE NOT FOUND, ERR: 4B UNSUPPORTED STORAGE TYPE , ERR 50: FILE IS (ALREADY) OPEN , ERR : 5A FILE STRUCTURE DAMAGED (BIT-MAP defekt) .
$C9: NEWLINE PARMCOUNT = 3 Referenz-Numm er - 1 Byte AND-Maske - 1 Byte Ende-Zeichen - 1 Byte
218
10. Mehr PRO als CONTRA
Das Command NEWLINE kann nur auf OPEN Fi les angewa ndt we rden und setzt ei ne End-Bed ingung für READ. Wen n NEWLINE aktiv ist , wird bei jedem Byte , das via READ gelesen wi rd , zuerst mit dem Masken-Byte ein AND durchgeführt. Danach erfolgt ein Vergleich mit dem E nde-Zeichen. Bei Übereinstimmung wird READ beendet. Das BASIC.SYSTEM setzt fü r Textfiles die Maske auf $7F und das E nde-Zeichen auf $OD. Damit endet jedes READ spätes tens bei einem ($8D oder $OD). Ist die Maske auf $00 gesetzt , ist NEWLINE deaktiviert. Fehler: ERR 43: INVALID REFERENCE NUMBER.
$CA: READ
PARMCOUNT = 4 Referenz- Nummer - 1 Byte Zielpuffer - 2 Byte-Adresse Anforderun gs-Zäh ler - 2 Bytes Übertragungs-Zäh ler - 2 Bytes Result at READ kann nur auf OPEN Files angewendet werde n. Es we rden die im Anfo rderu ngs-Zähler angegebenen Bytes ab der momentanen "Position im File" in den Zielpuffer gelesen. Vor READ wird EOF (END OF FILE) geprüft und die zu übertrage nde A nza hl an Bytes gegebenenfa lls herabgesetzt. Ist das EOF bereits erreicht , folgt ERR 4C: END OF FILE ENCOUNTERED. Bei akti vem NEWLINE endet READ ebenfalls, wenn das Ende-Zeichen erkannt wurde. NEWLINE setzt die Lesegeschwindigkeit bei größeren Datenmengen deutlich herab, da READ für A nforderungen vo n kompletten Blöcken ansonsten über einen "Schn ellgang" verfügt, der direkt ins Zielgebiet und nicht in einen Zwischenpuffer liest. Wenn nicht der gesamte Ziel puffer als frei markiert ist , folgt ERR 56: BAD BUFFER ADDRESS. Nach dem E nde vo n READ wird im Pa rameterblock der Übertragungs-Zäh ler mit der A nzahl der tatsächlich transferierte n Bytes besetzt . READ ve rschiebt di.e "Position im Fi le" um die A nzahl der gelesenen Bytes. Fehler : ERR: 27 IIO ERROR , ERR 43: INVALID REFERENCE NUMBER , ERR 4E: FILE ACCESS ERROR (B it 0 nicht gesetzt), ERR: 5A FILE STRUCTURE DAMAGED (BIT-MAP defekt).
10.1 G ute Ko ntakte per Sch ni ttstelle
219
$CB: WRITE PARMCOUNT = 4 Referenz-Nummer - 1 Byte Quellpuffer - 2 Byte-Adresse Anforderun gs-Zäh l er - 2 Bytes Übertr agu ngs-Zäh l er - 2 Bytes WRITE kann nur auf OPEN Fi les angewendet werde n. Es werden die im A nforderu ngs-Zähler angegebenen Bytes ab der momentanen " Position im Fi le" aus dem Quellpuffer in de n File geschri eben. Der File wird gegebenenfalls durch A nh ängen weite rer Blocks und Erhöhung des Storage Type erweitert. A uch der EOF erhöht sich . Das MLI versucht imm er , alle angeforderten Bytes auf den File zu schreiben . E in A bbruch kann nur durch eine Fehl erbedingung erfo lgen. Bis zu 512 Bytes werden zun ächst in ein em Zwischenpuffer gehalten. E rst wenn der Puffer voll ist , die Datei mit CLOSE geschlossen oder der Puffer mit FLUSH entleert wird , werden sie tatsächlich auf die Diskette geschriebe n. Damit alle Dateien voll ständig sind , so llten Sie jede Datei schli eßen, bevor Sie eine Diskette wechseln oder den Rechner ausscha lten. Nach Beendigung von WRITE wird in den Übertragungs-Zähler im Parameterblock die A nzahl der ta tsächlich geschri ebe nen Bytes eingetrage n. Während WRITE verschiebt sich die "Positi on im Fil e" um die Anzahl der geschriebenen Bytes. Fehler: ERR: 27 IIO ERROR, ERR: 2B WRITE PROTECTED , ERR 43: INV ALID REFERENCE NUMBER, ERR 48: VOLUME FULL , ERR 4E: FILE ACCESS ERROR (B it 1 nicht gesetzt), ERR: 56 BAD BUFFER ADDRESS, ERR: SA FILE STRUCTURE DAMAGED (BIT-MAP defekt) .
$CC:CLOSE PARMCOUNT = 1 Referenz-Nummer - 1 Byte oder $00 ("All e " ) Dieses COMMAND schreibt den 1I0-Puffer auf den OPEN File und akt ualisiert den Dateieintrag. Der Fil e-Puffer wird wieder freigegeben. Bei einer spezifizierten Referenz-Nummer muß das F il e OPEN sein , so nst fo lgt ERR 43: INVALID REFERENCE NUMBER. Bei einem "A ll e" (= $00) werden all e OPEN Files gesch lossen , wenn gleichzeitig das LEVEL-Byte ($BF94) auf $00 gesetzt wurde. CLOSE ruft FLUSH auf.
220
10. Mehr PRO als CONTRA
Bei einem "A lle" werden Fehlernummern zwischengespeichert , d .h es werden all e OPEN F iles wirklich bearbeitet. Fehler : ERR: 27 VO ERROR, ERR: 2B WRITE PROTECTED, ERR: SA FILE STRUCTURE DAMAGED (BIT-MAP defekt).
$CD: FLUSH
PARMCOUNT = 1 Refere nz-Nummer - 1 Byte oder $00 ("Alle " ) Dieses COMMAND arbeitet wie CLOSE , nur daß de r File nicht geschl ossen und sein Puffer nicht fre igegeben wird. Wenn längere Zeit nicht auf ein File geschrieben wird , können mit FLUSH zwangsweise der VO-Puffer geleert und die Dateieinträge aktualisiert werden. Bei einem "A lle" muß $BF94 (LEVEL) $00 sein , um all e Files zu bearbeiten. Fehler: ERR: 27 VO ERROR, ERR: 2B WRITE PROTECTED , ERR: 43 INVALID REFERENCE NUMBER , ERR: SA FILE STRUCTURE DAMAGED (BIT-MAP defekt).
$CE: SET MARK
PARMCOUNT = 2 Refer enz-Nummer - 1 Byte Position gewünscht - 3 Bytes (Lo/Mid/Hi ) Dieses COMMAND ka nn nur auf OPEN Files angewandt werden. Es setzt die "Position im File", die für den nächsten Z ugriff mit READ oder WRITE benutzt wird. Wird vom Benutzer eine Position spezifiziert , die hinter dem momentanen EOF des Fi les liegt, fo lgt ERR 4D : POSITION OUT OF RANGE . Das erste Byte der Datei hat die Position $000000 . Wegen der möglichen Maximall änge ei nes Fi les muß die "Position im Fi le" ein e 3-Byte-Zahl sein , wo bei das niederwertigste Byte vo rne steht. Fehl er: ERR: 43 INVALID REFERENCE NUMBER , ERR: SA FILE STRUCTURE DAMAGED (BIT-MAP defekt).
$CF: GET MARK
PARMCOUNT = 2 Refe renz-Nummer - 1 Byte Position im Fil e - 3 Byte-Resultat (Lo/Mid/Hi)
10.1 Gute Kontakte per Schnittstelle
221
Dieses COMMAND kann nur auf OPEN Files angewandt werden . Es kopiert die momentane "Position im File" , also den Start des nächsten READ oder WRITE, in den PARMBLOCK. Fehler: ERR 43: INVALID REFERENCE NUMBER
$DO: SET EOF PARMCOUNT = 2 Referenz-Nummer - 1 Byte neuer EOF - 3 Bytes (Lo/Mid/Hi) Dieses COMMAND kann nur auf OPEN Files angewandt werden. Es setzt den EOF (End Of File ~ Dateigröße) eines Files. SET EOF ist nur für Datenfiles und nicht für Subdirectories möglich. Ist WRITE nicht erlaubt (Bit 1 im Access-Byte gelöscht) , fo lgt ERR 4E : FILE ACCESS ERROR. Bei einer Vergrößerung des EOF entstehen sogenannte "Loch-Dateien", deren Blöcke beim nächsten WRITE belegt werden. Bei einer Verkleinerung des Files werden Blöcke aus dem File wieder fre igegeben und innerhalb der Master/Indexblock(s) gelöscht. Feh ler: ERR: 27 IIO ERROR , ERR: 43 INVALID REFERENCE NUMBER, ERR: 4D POSITION OUT OF RANGE, ERR : SA FILE STRUCTURE DAMAGED (BIT-MAP defekt) .
$Dl: GETEOF PARMCOUNT = 2 Referenz-Nummer - 1 Byte EOF - 3 Byte-Resultat (Lo/Mid/Hi) Dieses COMMAND kann nur auf OPEN Files angewandt werden. Es kopiert den momentanen EOF des Files in den PARMBLOCK. Fehler: ERR 43: INVALID REFERENCE NUMBER
$D2: SET BUF PARMCOUNT = 2 Referenz-Nummer - 1 Byte Pufferstart - 2 Byte-Adresse (Lo/Hi) Dieses COMMAND kann nur auf OPEN Files angewandt werden . Es setzt einen ne uen Fi lepuffer, wobei der Inha lt des alten in den neue n Fi lepuffer
222
10. Mehr PRO als CONTRA
kopiert und der alte Filepuffer wieder freigegeben wird. Alter und ne uer Puffer dürfen sich nicht überschneiden , das La-Byte der Adresse muß $00 se in . Ist der Bere ich des neuen Filepuffers ($400 Bytes) nicht vollständig frei , folgt ERR 56 : BAD BUFFER ADDRESS. Fehler: ERR : 43 INVALID REFERENCE NUMBER $D3: GETBUF
PARMCOUNT = 2 Referenz-Nummer - 1 Byte Pufferstart - 2 Byte-Adresse Resultat (Lo/Hi) Dieses COMMAND kann nur auf OPEN Files angewandt werde n. Es schreibt die Startadresse des zugehörigen Filepuffers in den PARMBLOCK. Fehler: ERR 43: INVALID REFERENCE NUMBER.
10.2 Wie spreche ich mit ProDOS? Unter DOS 3.3 ist es eine gä ngige Praxis , Diskettenbefehle mit einem vo rangestellten Ctrl-D als Zeichenkette über COUT auszugeben. Unter ProDOS funktioniert dieses Verfahren nicht mehr. We nn nur PRODOS.SYSTEM im RAM ist , gibt es keine Möglichkeit mehr , mit Strings ein en Diskettenbefehl auszuführen . Befindet sich allerdings auch das BASIC.SYSTEM im Speicher was zur Ausführung eines Applesoftprogramms notwe ndig ist - , dann existiert eine A lternative : a) Sie legen die Zeichen kette (z.B. CATALOG) ohne Ctrl-D ab $0200 in den Tastatureingabe-Puffer. Das Bit 7 vo n jedem Zeichen muß gesetzt sein . Die Zeichen kette muß mit $8D (RETURN) abgeschlossen werden. b) Sie rufen den Co mm and-Handl er auf (JSR $BE03). Wurde der Befehl korrekt ausgeführt , ke hrt die Routine mit ge löschtem CarryBit zurück. Bei einem Feh ler erfo lgt eine Fehlermeldung und ein Programmabbruch. Die Befehle -, RUN, LOAD, CHAIN, OPEN, READ , WRITE, APPEND, POSITION, EXEC , IN* und PR* sind auf diese Weise nicht ausführbar. Noch von einer weiteren lieben Gewohn heit müssen wir uns unter ProDOS verabschieden . U nter DOS 3.3 konnten Sie die E in- lind A usgabe des Apple
10.3 Wo find' ich ein Zuhause?
223
umlenken , indem Sie di e neuen Ad ressen in die Vektoren CSW ($0036/37) und KSW ($0038/39) schrieben und anschließend die Routine CONNECT (JSR $03EA) aufriefen. Da die Adresse $03EA nicht mehr in Funktion ist , können Sie dieses Verfahren unter ProDOS nicht mehr anwenden. Wenn das BASIC.SYSTEM im Speicher steht, gibt es fol gende Alternative: a) Sie lasse n CSW und KSW unverändert. b) In den Ausgabe-Vektor $BE30/31 tragen Sie die gewünschte Ausgabeadresse ein (norm al COUTl $FDFO). c) In den E ingabe-Vektor $BE32/33 tragen Sie die gew ünschte E inga beadresse ein (normal KEYIN $FDlB). Das ist alles!
10.3 Wo fmd' ich ein Zuhause? Wenn Sie ein BASIC-Programm und ein Assembler-Programm gleichzeitig im Speicher halten wollen , benötigen Sie einen sicheren Ort für den Maschinencode. Vor allen Dingen muß er vor dem Übe rschreiben durch BASIC-Variablen geschützt werden. Wenn der Platz von $0300 bis $03CF nicht ausreicht , müssen wir einen anderen Platz wählen. U nter DOS 3.3 wurde zumeist der RAM-B ereich unter den DOS-Puffern (unterhalb $9600 bei MAXFILES 3) gewählt und dann HIMEM: unter das Programm gesetzt. Auch dieses Verfahren funktioniert unter ProDOS nicht mehr , denn ProDOS hat eine dynamisch e Pufferverwaltung. Das heißt , daß ProDOS selbsttätig Puffer einrichtet und löscht. Den Befehl MAXFILES gibt es nicht mehr. Das BASIC.SYSTEM liegt von $9AOO an aufwärts im RAM. Darunter befindet sich von $9600 (HIMEM:) bis $99FF ein Allzweckpuffer. Wird ein File geöffnet (OPEN) , wird dieser Allzweckpuffer nach $9200 (neues HIMEM:) verschoben und ab $9600 ein Filepuffer eingerichtet. Jedes weitere OPEN verschiebt den Allzweckpuffer und HIMEM: um weitere 1024 Bytes nach unten (bei 2 offenen Files nach $8EOO) und setzt den neuen Filepuffer an die alte Adresse des Allzweckpuffers (= unter den letzte n Filepuffer) . Lediglich bei einem EXECFile werden alle Puffer nach unten verschoben und der EXEC-Filepuffer bei $9600 eingerichtet. Wenn Files geschlossen (CLOSE) werden, wird der zugehörige Puffer aufge hoben und all e übrigen Puffer werden wieder nach oben geschoben.
224
10 . Mehr PRO als CONTRA
Der einzige sichere Ort für ein Assembler-Programm liegt zwischen dem BASIC.SYSTEM (BI) und den Filepuffern. Das BASIC.SYSTEM kann eine beliebig große Anzah l von Speicherseiten (je 256 Bytes) zwischen sich und dem ersten Puffer freihalten. D ie Anzahl der gewünschten Seiten ist in den Akkumulator zu laden und dann GETBUFR ($BEF5) aufzurufen. Wen n das Carry-B it gelöscht ist , war die Einrichtung des geschützten Bereichs erfolgreich. Der Akkumulator enthält dann das H i-B yte der unteren Pufferadresse (das Lo-Byte ist immer $00 , X- und Y-Register werden zerstört!). Der erste geschützte Bereich wird immer direkt unterhalb des BASIC.SYSTEM ($9AOO) eingerichtet , ega l wievie le Fi lepuffer gerade geöffnet sind. Seine Adresse ist deshalb vorhersehbar und Sie benötigen keinen relokativen Code für Ihr Assembler-Programm. Fordern Sie über GETBUFR weiteren Speicher an , so wird dieser unterhalb des zuletzt reservierten Bereichs eingerichtet.
LDA JSR BCS STA LDA STA
t2 GETBUFR FEHLER SPEICHER+l t$00 SPEICHER
; 512 Byt es freihalten ;Anforderung ; Fehlerbehandlun g ;Hi-Byte des Pufferanfangs ; Lo-Byte
Ab (SPEICHER) können Sie dann Ihr Masch inenprogramm laden. Sie können nachträglich auch noch weitere Programme in den reservierten Bereich laden , da ProDOS ihn intern (i n der System Bit Map , auf die wir hier nicht eingehen) als nicht belegt markiert hat. Sie können den reservierten Bereich nur als Ganzes wieder fre igeben. Dazu ist ein JSR FREEBUFR ($BEF8) notwendig. Die Fil epuffer werden dann wieder unter das BASIC.SYSTEM gesetzt. Wenn Sie Maschinenprogramme benutzen woll en , die unter DOS 3.3 geschrieben wurden (praktisch alle Programme dieses Buches) , ist zu beachten: a) Wenn das Programm völlig selbständig arbeitet und keine A ufrufe an das DOS macht (ROM-Aufrufe funktionieren weiterhin) , kann es den gesamten Speicher bis $BEFF belegen, da das BASIC. SYSTEM dann nicht benötigt wird. b) Wenn das Programm DOS-Aufrufe macht , sind die betreffenden Tei le völlig umzuschreiben. Entweder muß das MLI benutzt werden - dann ist nur PRODOS.SYSTEM notwendig - oder auch das BASIC.SYSTEM (dann ist der Speicher nur bis $9600 frei).
10.3 Wo find' ich ein Zuhause?
225
c) Wenn gleichzeitig auch Applesoft benutzt wird, muß das Masch in enprogramm zwischen dem BASIC.SYSTEM und den Fi lepuffern "versteckt" werden (siehe oben). Die entsprechenden Routinen sind zu ergänzen , der ORG muß angepaßt werden. Dafür sind alle Teile , die HIMEM: versetzen, zu streich en. Noch eine Schlußbemerkung: In diesem Buch ist nicht ausreichend Platz, um Beispielprogramme für alle neuen Möglichkeiten des ProDOS zu zeigen. "Appie ProDOS für Aufsteiger, Band 1 und 2" von Ulrich Stiehl, Hüthig Verlag He idelberg, gibt Ihnen viele kleine und große Anregungen für eigene Programme .
226
11. Schnell wie der Wind Dieses ist das letzte Ka pitel in dem zweibändigen Kursus "A pp le-A sse mb ler le rn en" . Sie ha ben bis jetzt fast alles gelernt , was man über die Assemb lerprogrammierung des 6502/65C02 wissen mu ß, und Sie haben se hr viel über Ihren A pple erfahre n . Kein Kursus kann alle Themenbereiche einer Sach e vollständig abdecken. Zwei Dinge haben wir völlig ausgelassen: die Steue rung des R echners mit Inte rrupts und di e A nwe ndung und Progra mmierun g der Maus. E in dritte r Be reich ist noch nicht ganz behandelt worde n: die Programmierun g von D iskettenzugriffen . W ir haben zwa r gelernt , mit D OS 3.3 und ProD O S umzugehe n, aber das ist nicht der einzige Weg . Die Betriebssysteme sind ja auch nur wieder Assembler-Programme , derer wir uns bedie nt habe n . Es gibt danebe n noch den ganz direkte n Weg durch das A nsprechen des Disk-Controlle rs und seine r Ha rdware-Ad ressen. In diesem Kapitel we rden wir nun ein schnelles Ko pierprogramm für D OS-, ProDOS-, CP/M- und PASCAL-D iskette n schreiben , das in ein em A rbeitsgang eine normale 35 Track Diskette fo rmatiert und ko pi ert. D iese A ufga be ist nur zu meistern , wenn wir di re kt die Hardwa re des Diskette n-Contro llers ansteuern. Da Sie nun schon ein recht e rfahrener Programmi ere r sind , we rde ich Ihnen keine Programm beschreibung mehr liefe rn . D as Listing ist aber reichlich kommentiert , sodaß Sie viele H ilfe n zu m Verständnis haben . E in paar D inge habe n wir noch nicht anges proche n, di e unbedingt zum Ve rstehe n eines Ko pierprogramms notwe ndig sind: der Aufbau ein er D iskette und die H ardware des Co ntro llers. Vo r dem eigentli chen Programm werden wir uns deshalb noch mit diesen T hemen beschäftigen müssen .
227
11.1 Rund und dunkelbraun
11.1 Rund und dunkelbraun E in e Diskette ist eine magnetisierbare Scheibe ähnlich ein em Tonband . Die Diskette wird beschrieben und von ihr wird ge lesen, während sie sich mit 300 Umdrehungen pro M inute unter einem Magnetkopf herbewegt. Auf diese Weise werden kreisförmige Spuren bearbeitet. Der Kopf kann radial bewegt werden und so verschiedene Spuren erreichen. Beim DISK II Laufwerk von Apple sind es 35 Spuren (= Tracks). Der Kopf wird durch einen Schrittmotor gesteuert , der unter der Kontrolle des 6502-Prozessors steht. Der Apple hat also keinen eigenen D isk-Prozessor. Es ist ferner kein Sensor vorhanden , der dem Rechner die absolute Kopfposition mitteilt . DOS und ProDOS ziehen deshalb den Kopf bis an einen mechanischen Ansch lag (Spur 0) , was das berühmte "Klappern" bewirkt . Von da an werden alle Kopfbewegungen im RAM protokolliert , damit die Betriebssysteme die Kopflage kennen. Auf jede Spur ist außerdem ein Bitmuster geschrieben , in das u.a. auch die Spurnummer codiert ist. Vor der ersten Benutzung muß eine Diskette formatiert werden. Dabei wird ein festgelegtes Bitmuster auf sie geschrieben , das eine Spur in 16 Datenfelder für je 256 Bytes aufteilt , die als Kreissegmente gleichmäßig auf der Spur verteilt liegen. E ine solche Diskette wird "softsektoriert" genannt im Gegensatz zu den heute nicht mehr gebräuchlichen hardsektorierten Disketten , bei denen jedes Datenfeld mÜ einem Loch in der Diskette gekennzeichnet war. Vor jedem Datenfeld liegt noch ein kleines Adressfeld, das die Nummer des Sektors , des Tracks und des Volumes der Diskette enthält. Adress- und Datenfeld bilden zusammen einen Sektor. Vor und hinter dem Adressfeld sowie vor und hinter dem Datenfeld befinden sich noch ein paar Bytes (je 3) , die einen Prolog (He ader) bzw. Epi log (Trailer) bi lden und zur Identifizierung der Felder dienen. Die Sektoren sind eingebettet in eine besondere Art von Bytes, den Synchronisations-Bytes (Syncs) , die dafür verantwortlich sind , die Elektronik des Controllers und den Datenstrom auf der sich drehenden Diskette im Gleichtakt zu halten. Es würde an dieser Stelle etwas weit führen, alle Details zu behandeln. Eine gute Beschreibung finden Sie in "Beneath Apple DOS", Quality Software. Der prinzipielle A ufbau eines Sektors lautet:
5-40 Syncs FF FF FF ... FF FF
Prolog 05 AA 96
5-8 Syncs FF FF FF ... FF FF
Prolog 05 AA AO
Volume Track Sektor Prüfsumme Epilog VOL VOL TRK TRK SEC SEC SUM SUM OE AA EB Da t e n 342 Oa t enb yt es
Prüfsumme SUM SUM
Epilog OE AA EB
228
11. Schne ll wie de r Wind
Sie werde n sich siche rlich wundern , wa rum hier 342 D ate nb ytes angegeben sind , o bwohl doch nur 256 Bytes im Sekto r ges peichert werden. D es R ätsels Lösung liegt in einer spezielle n Codi erun g, da die Speicherb ytes nicht einfach so auf di e Diskette geschrie ben we rde n können. A uf diese Weise werde n aus 256 Bytes im R AM die 342 Bytes des Diskettense kto rs. Be im Lesen müssen sie wiede r in 256 R AM-Bytes zurückverwa ndelt we rd en. Sowo hl am E nde des Daten- als auch des A dressfeldes liegt eine Prüfsumme , mit de r kontrolliert werden kann , ob di e Bytes des Feldes korrekt gelesen wurde n . Sie entsteht dadurch , daß alle Bytes eines Fe ldes beim Schreibe n mitein ander in eine r Kette EOR-verknüpft werd en. Die Zeit , in der 1 Byte auf di e D iskette geschriebe n wird , beträgt 32 Microseku nden oder 4 Prozessortakte pro B it. Da die U mdrehu ngsgeschwindigkeit einer D iskette ni e so ko nsta nt ist , daß auf ein Bit genau geschri eben ode r gelesen we rden kann , sind die Se kto re n "schwimm end" in die Sync-Bytes eingelagert, die 3 unterscheid bare Ty pe n vo n Zwische nräumen (GAP) bilden . Der größte Zwischenraum (GAP1) liegt zwischen A nfa ng und E nde ei ner Spur , da sich de r erste und le tzte Se ktor nicht überl appen dürfe n . Wir finden hier typischerweise ca . 70 Syncs . Zwischen den übrigen Sektore n liegt GAP3 mit ca. 20 Syncs . E in weiterer kleiner Zwischenra um (GAP2) li egt zwische n dem A dress- und D atenfeld eines Sektors. E r umfa ßt norm al 5-8 Syncs .
_L---IIL-.._.~II,--___~ GAP 1
Adre ssfeld
GAP 2
Dotenfeld
GAP J
Adres sfe ld GAP 2
Dafenfeld
GAP J
A bb . 12 : A ufba u ein es T rac ks
D ie absolute Länge des GAPs ist nicht ko nstant , da das Form atie rprogramm sie an die Geschwindigkeit des Laufwe rks anpaßt. E in langsa mes Laufwe rk hat längere GAPs als ein schnelles . Z um zweite n wird der U mfang eines Tracks imme r geringer , je weiter inn en der Track auf der D iskette liegt. Auch di ese U nterschi ede werden mit de n GAPs aufgefangen. D ie Formatierprogra mme der Firm a A ppl e sind imme r be müht , die Sektoren gleichmäßig über de n U mfa ng des T racks zu ve rteilen. E inige Schnell kopie rer mache n sich diese Mühe nicht. Sie wä hl en die GAPs 2 und 3 so kurz, das es auf einem schnelle n D ri ve und der innersten Spur noch reicht. Der A usgleich fin det nur über GAPl statt , wä hrend z.B . DOS sowohl GAPl als a uch GAP3 für jede D iskette einzeln a npaßt.
229
11 .1 Rund und dunkelbrau n DOS 3.3 GAP 1 GAP2 GAP3
Locksmith 5.0
73 7
19
107 8 16
Superquick
Byte- Blizzard
119 8
71 7
15
20
Sync-Bytes auf Track 0 (Mittelwerte aus 3 Messungen, DOS 3.3 = COPY A) Die ungleichmäßige Verte ilun g der Sektoren führt all erdings nach mein en Untersuchungen zu keinen meßba ren Geschwindigkeitsproblemen beim Lesen oder Schreiben (warum Locksm ith-kopierte Disketten sich langsa mer lesen, fo lgt später). Der Datenaustausch zwischen Rechner und Laufwerk führt über ein Datenregister auf dem Controller. Der normal e Weg , einen Sektor zu lesen, besteht darin, den Kopf auf die gewünschte Spur zu positionieren und solange das Datenregister zu lesen, bis das gesuchte Adressfeld vorbeikommt. Das unmittelbar fo lgende Datenfe ld wi rd dann ins RAM gelesen und wieder decod iert. DOS liest immer ei nen ganzen Sektor auf einmal , ProDOS soga r 2 Sektoren (= 1 Block). Geschrieben wird ga nz ähnlich. Zunächst wird solange das Datenregister gelesen, bis das gewünschte Adressfeld vorbeikommt. danach wird sofort auf "Schreiben" umgestellt und das alte Datenfeld mit neuen Daten überschri eben. Zwischen dem Prozessor des App le und dem Datenregister werden die Information en byteweise (= parallel) ausgetauscht. Vom Co ntroller we rden die Daten dann bitweise (= seriell) auf die Diskette geschri eben, alle 4 Mikroseku nde 1 Bit. Bei m Schreiben muß der Prozessor dem Datenregiste r exa kt all e 32 Mikrosekunde (8*4) ein Byte zur Verfügung stellen, damit der Datenstrom aufrecht erhalten werden kann . Das genaue Tim ing ist eine der schwierigsten Aufgaben für den Progra mmierer. Das Lesen ist ve rgleichsweise einfac h: hier wartet der Prozessor ein fach ab, bis ein Byte vollständig ist. Dies ist daran zu erke nnen , daß Bit 7 des Datenregisters gesetzt ist. Es wird eine Abrufschleife (Polling Loop) von 7 Takten Länge benutzt: LOOP LDA DATENREG BPL LOOP
Achten Sie darauf, daß nicht zufä llig ei ne Seitengrenze zwischen LOOP und dem Branch liegt, da sonst die Schleife 8 Takte benötigt und unzuverlässig wird!! Noch eine kleine Anmerkung: Sync-Bytes entstehen , wenn ein $FF dem Datenregister übergeben wird und dann 40 Mikrosekunden bis zum nächsten
230
11. Schnell wie de r Wi nd
$FF vergehen . Dadurch wird die Bitfolge 1111111100 auf die Diskette geschrieben (lO-Bit-Byte).
11.2 Von halben Bytes und 6&2 A uf Grund von Hardwa rebeschränkun gen muß ein Disk-Byte folgende Voraussetzungen erfüll en: a) Bit 7 muß gesetzt sein b) maximal zwei aufei nanderfolgende Bits dürfen gelöscht sein c) von solchen Paaren (b) ist nur ein es im Byte erlaubt. A uf einer norm alen 16-Spur-D iskette werden nun zwei Codierverfahren benutzt , um aus Speicher-Bytes die Disk-Bytes werden zu lassen . Das erste fi ndet sich nur im Adressfeld und wird als 4&4-Codierung bezeichnet. Jedes Speicher-Byte wird einfac h in zwei Bytes aufge teilt und die Lücken mi t 1 gefüllt: A us ABABABAB wi rd 1A1A1AIA und 1B1B1BlB. Der Nachteil dieses Verfa hrens ist , daß sich die Byteanzahl verdoppelt und damit die Speicherkapazi tät der Diskette sinkt. Sein Vorteil ist die Schn elligkeit , in der Codierung und Decodierung erfo lgen kö nnen . Deshalb wird diese 4&4-Codierung auch für die Ad ressfelder benutzt. Die 6&2-Codierung verpackt nun die Speicher-Bytes etwas ökonomischer , aber zugleich auch wesentlich komplizierter. A us 3 Speicher-Bytes werde n dabei nur 4 Disk-Bytes. Vo n jedem der 3 Speicher-Bytes werden die beiden unte rsten B it in einen Zwischenpuffer gespeichert. Die verbli ebenen 6 oberen Bits werde n zweimal nach rechts geschiftet . D ie entstehenden Rest-Bytes haben dadurch Werte zwischen %00000000 und %00111111 ($00 - $3F). Die dreimal zwei unteren Bits werden wiederum zu einem Rest-Byte zusammengesetzt . Der Bereich von $00 bis $3F umfaßt 64 verschiedene Mögli chkeiten. Zwichen $95 und $FF gi bt es 72 gül tige Disk-Bytes. Zwe i davon ($D5 und $AA) we rde n reserviert für Epi- und Prolog. Von den restlichen 70 werden nur die 64 benutzt , die wenigsten ein 11-Paar enthalten. Die U msetzung der Res t-B ytes in die D isk-Bytes geschieht über eine Tabelle. Auf diesem Wege werde n aus 256 Speicher-B ytes die 342 Disk-Bytes. Bei m Lesen müssen die Disk-Bytes wieder mit einer Tabelle in Rest-Bytes umgesetzt LInd anschließend zu den Speicher-By-
11.2 Von halben Bytes und 6&2
231
tes zurückgewande lt werden . Die erforderl ichen Programme für beide Richtungen sind recht komplex . E in Schritt wurde bisher nicht ganz richtig erklärt: die Reihenfolge , in der die Disk-Bytes auf die Diskette geschrie be n werden. Die Codierroutin e, auch "Prenibble" genannt, schreibt die beiden unteren Bits jedes Speicher-Bytes in vertauschter Reihenfolge in den Zwischenspeicher. Zusätzli ch werden die o be ren 6 Bits von unten nach oben im Speicher gelesen , die unteren 2 Bits aber von oben nach unten im Zwische nspeicher abgelegt. Die 256 Speiche r-B ytes werden gedrittelt und die Rest-Bytes im Zusatzpuffer werden zu je 2 Bits aus jedem Drittel zusammengesetzt. Das hört sich ungeheuer kompliziert an , ist aber in Asse mbler relativ einfach zu verwirklichen.
AAAAAAarn BBBBBBbn CCCCCCco DDDDDDdp EEEEEEeq
OOAAAAAA OOBBBBBB OOCCCCCC OODDDDDD OOEEEEEE
F'F'F'F'F'F'fr
OOF'F'F'F'F'F'
GGGGGGgs HHHHHHht
OOGGGGGG OOHHHHHH
IIIIIIiu
OOIIIIII
JJJJJJjv KKKKKKkw LLLLLLlx
OOJJJJJJ OOKKKKKK OOLLLLLL
Speicher-Bytes
Rest-Bytes Hauptpuffer
OOxlthpd OOwksgoc OOvjrfnb OOuiperna
Rest-Bytes Zusatzpuffer
Da sich 256 nicht o hn e Rest durch 3 teilen läßt, wird das letzte Drittel um zwei ungültige Bytes ergä nzt. W ir erhalten 256 Bytes im Hauptpuffe r und 86 Bytes im Zusatzpuffer. Auf die D iskette werden zunächst die Bytes aus dem Zusatzpuffer geschri eben und dann die Bytes des Hauptpuffers. A ls 343 . Byte schließt sich die Prüfsumme an, die sich aus der EOR-Ve rknüpfung der vora nstehe nde n 342 Bytes e rgibt. Der ganze Codierprozess ist sehr zeitaufwendig. Es ist nicht möglich, alle 32 Prozessortakte ei n Byte "fert ig" zu haben. Bei DOS und ProDOS wird deshalb das Cod ieren ein es Sektors vor dem Schreiben vorge nommen . Es ist nicht möglich, ein en Track bei einer D iskettenumdrehung zu beschreiben , weil die Pausen zwische n den Sektoren für die Cod ierung nicht a usreichen. DOS liest ein en Sektor in ein en Zwischerp uffe r und decod iert ihn nachträglich. Deshalb wird a uch hier ein Track nicht in einer Umdrehung gelesen. ProDOS ist dazu in der Lage, da die Decod ierung durch viele Tabellen direkt während des Lesens passiert.
232
11. Schnell wie der Wind
Bei einem schnelle n Kopierprogramm gibt es zwei Lös ungen : a) Die Disk-Bytes we rde n gar nicht decodie rt , sond ern im R AM zwische ngespeichert und vo n do rt un verände rt herausgeschrie ben . Diese Lösung ist e infac h, verbraucht aber viel Speiche r. b) Die Disk-Bytes werden decodi e rt, aber nach ein em a nderen Ve rfahre n. A us de m R A M werde n sie mit de r Gegenmethode wiede r zurückcodiert. Diese Lösung ist pl atzspare nd , aber kompliziert. U nser Kopie rprogra mm ve rwe ndet di e Methode b), die vo n O mega Ltd . für Locksmith "erfunden" wurde. De r zeitkritische Teil ist das Codie re n, nicht das D ecodiere n . D as Codie re n braucht viel Zeit , weil erst der Z usatzpuffe r aufgebaut werde n muß , da e r zuerst geschriebe n wird . Di e Lös ung steckt in folgende r Ü be rlegung: E in Ko pie rprogramm muß im RA M gar ni cht gültige Speicher-Bytes erze uge n. Es ist nu r wichtig, daß hinterher auf der Ko pi e die se Ibe n Disk-Bytes stehen . E in Sektor wird deshalb in V iere rgruppe n gelese n. Di e 6 gültigen Bits des erste n Bytes we rden einfach in die 2 freie n Bits der nac hfo lgende n 3 Bytes gepackt. D adurch e ntstehe n 258 Bytes (3*86). D ie 2 "übrigen" Bytes werde n in eine n Z usatzpuffe r geschrieben, da so nst jeder Sekto r me hr als eine Speiche rseite einn ehme n würde . Beim Schreiben der Kopie wird zun ächst das 1. Disk-Byte a us de n 3 erste n Bytes im R AM wieder he rausgelöst. Wä hre nd dann diese 3 Bytes geschrie be n we rden , ist genug Z eit , das 4 . D isk-Byte aus den nächsten 3 Bytes herauszulösen usw. A uf diese Weise ist es möglich , eine n Track in ein e r U mdrehung zu lesen und auch zu schreiben.
11.3 Viele kleine SchaIterchen Die Softswitches des Apple haben wir früh e r schon einmal ke nnengele rnt. A uch de r Disk-Cont rolle r besitzt 16 so lcher Ad ressen , die A n- und A usschalter für 8 Funktion en darstelle n . Sie liegen im Adressbereich $C080 ,X bis $C08F,X, wobei das X-Registe r de n 16-fache n We rt der Slotnummer e nthält. Ge rade A dressen schalte n "AUS" , ungerade "E IN" . $C080,X $C081,X $C082 ,X $C083 ,X
Phase Phase Phase Phase
0 a us 0 ein 1 aus 1 ein
11.3 Viele kleine Scha lterchen $C084,X $C085,X $C086,X $C087 ,X
Phase Phase Phase Phase
233
2 aus 2 ein 3 aus 3 ei n
$C088,X Motor aus $C089 ,X Motor ein $C08A,X Laufwerk 1 anwäh len $C08B ,X Laufwerk 2 anwä hlen $C08C ,X Datenregister übertragen $C08D,X Datenregister laden $C08E ,X Lese-Modus setzen $C08F ,X Schreib-Modus setzen Die Phasen gehören zum Steppenllotor des Kopfes. Wenn die Phasen in aufste igende r Reihenfolge angesprochen werden , bewegt sich der Kopf nach innen . Z ur Bewegung vo n einem Track zu m nächsten müssen 2 Phasen geschaltet we rden. Es existieren also 70 Positione n bei einer 35-Spur Diskette, die sogenann te n "Ha lf-Tracks", die abe r nur fü r Kopie rschutzmöglichkeite n ei ne Rolle spie len. Benutzt werde n nur die Positionen, die zu Phase 0 und Phase 2 gehören. Zu Track 0 gehört auch die Phase O. Für ei nen runden Motorl auf müssen definierte A nlauf- und Abschaltzeite n ein gehalten werden. Nach einem Spurwechsel muß dem Kopf eine Pa use zum A uspendeln gegeben werden. Die Laufwerksanwahl schaltet das La ufwe rk nicht an, so ndern wählt es nur für die nächste Benutzung vor. Die Ad ressen $C08C bis $C08F geben zusammen die Mögl ichkeit zu vier weite ren Tätigkeiten: $C08C mit $C08E: Datenregister lesen $C08D mit $C08E: Schreibschutz testen und Controller initi ali sieren $C08C mit $C08F: Datenregister all e 4 Takte um 1 B it weiterschieben $C08D mit $C08F: Datenregister beladen
234
11. Schnell wie der Wind
Beispiele:
Laufwerk anwähl en LDX U 60 LDA $C08A , X
Slot 6 Laufwerk 1
LDA $C08B,X
Laufwerk 2
Motor an/aus LDX U60 LDA $C088 ,X
Slot 6 Motor aus
LDA $C089,X
Motor an
1 oder mehrere Bytes lesen LDY LDA LDA LOOP LDA BPL LP2
U60 $C08E,X $C08C,X $C08C,X LOOP
LDA $C08C,X BPL LP2
;Slot 6 ; Lese-Modu s setzen ; Datenre gi ster normalisieren (1 Zugriff) ; Datenre gi ster laden ; bei MINUS ist Byte da ;siehe oben für jedes ; weitere Byte
Schreibschutz prüfen, Controller initi alisieren LDX LDA LDA BMI
U60 $C08D, X $C08E,X ERROR
;S l ot 6 ;B it 7 gesetzt, wenn schreibgeschützt
Schreiben mehrerer Bytes (vorher Controll er initialisieren) LDX U60 LDA BYTEl STA $C08F',X CMP $C08C,X
;Slot 6 ;Schreibmodus setzen ;schreiben
LDA BYTE2 STA $C08D,X ORA $C08C,X
;Wartezykl en einl egen ;2. Byte ;Datenregister l aden ;schreibe n
LDA BYTEn STA $C08D,X EOR $C08C,X
Wartezyklen ei nlegen n. Byt e Dat enregister l ade n schreiben
LDA $C08E,X LDA $C08C,X
Wartezyklen ein l egen Lesemodus setzen Datenregister normalisieren
; 1. Byte
11.4 D as wirbelnde Byte: Byte-Blizzard
235
Das Schreiben vo n Bytes ist sehr kritisch . Mit einem Test des Schreibschutzes muß zunächst der Controller initialisiert werden. Sodann wi rd das e rste Byte in den Akkumulator geladen und die Adresse $C08F,X angesprochen. Dadurch wird sowohl de r Schreibmodus gesetzt als auch das Datenregister gelade n. Mit eine m Zugriff a uf $C08C,X wird dieses Byte dann "a bgeschickt" . Ab jetzt läuft die Zeit. Das Laden des Datenregisters und das "Abschicken " des Bytes muß mit der indizierten Adressierung erfolgen. Ein absolutes Adressieren (z. B. STA $COEC) funktioniert nicht! Welchen Befehl Sie zum "Abschicken" nehmen , ist relativ gleichgü lti g: CMP, ORA oder EOR sind gleichermaßen geeignet und benötigen jeweils 4 Takte. STA ist nicht geeignet. Nach genau 32 Prozessortakten muß das Datenregister wieder geladen sein und sofort danach abgeschickt werden . Die Takte zäh len vom Begi nn des Absch ickens bis zum erneuten Abschicken. In dem Programm "Byte-Blizzard " sind an einigen Stellen die Takte mitgezählt, damit Sie eine Vorstellung von den Möglichkeite n ha ben . Achten Sie darauf, daß keine Seitenübergänge bei einigen Befehlen passieren: LDA $lFFO,X mit X =5 benötigt 4 Takte, mit X=$20 passiert ein Seitenübergang und es werden 5 Takte verbraucht. Außer dem 1. Byte werden alle übrigen mit der Kombination $C08D/$C08C geschrieben. Warten Sie nach dem Sch reiben des letzten Bytes a uch 32 Takte , bevor Sie den Lesemodus (LDA $C08E,X) wieder he rstellen. Wen n Sie hier ni cht la nge genug warten , wird Ihr Byte nicht vollständig geschri eben . Der Programmierer von DOS 3.3 hat z.B. eine zu kurze Pause gemacht, als er das Epi log-Byte $EB schreiben mußte. Es ist deshalb immer unvoll stä ndig und nicht korrekt lesbar. Warten Sie allerdi ngs mit dem Setzen des Lesemodus zu lange, schreibt der Controlle r aus dem leeren Datenregister lauter Nullen auf die Diskette. In ein e m Sekundenbruchtei l ist damit ein ganzer Track vernichtet!
Warnung: A lle Progra mme , die das Diskettenlaufwerk direkt ansprechen , können bei Programmierfehlern die eingelegte Diskette ruinieren. Probieren Sie deshalb solche Programme immer mit Di sketten , die auch gelöcht werden dürfen, in allen(!) Laufwerken aus. Es ist fe rn er ratsam , beim ersten Start jedes Assemb lerprogramms die Laufwerksklappen zu öffnen. Sicher ist Sicher!
11.4 Das wirbelnde Byte: Byte-Blizzard Das Kopierprogramm "Byte-Blizzard" kop ie rt eine normale 35-Track AppleDiskette auf einem Apple mit mindestens 64K Hauptspeicher in knapp 32 Se kunde n inclusive Fo rm atierung. Da die Fo rm atie run g fü r alle Betriebssy-
236
11. Schnell wie der Wind
sterne des Apple (DOS3 .3, ProDOS, PASCAL, CP/M) identisch ist und alle Sektoren übertragen werden , kann "Byte-Blizzard" Disketten von allen 4 Betriebssystemen kopieren. Jede geschriebene Spur wird zurückgelesen (Ver ify). In der fo lgenden Tabell e sind die Kopierzeiten für einige gebräuch liche Programme zusammengestellt. Bedingungen: 64K Apple IIe mit 2 Laufwerken DISK II am seiben Contro ll er in Siot 6, Mittelwerte aus drei handgestoppten Läufen inclusive Formatierung. Programm l. Locksmith 5 .0
2. 3. 4. 5. 6.
Superquick Byte-Blizzard COPY IIplus 5 . 5 CO PY II E "StiehP COPYA
Kopierzeit 26,6 30,5 31 , 8 41 , 9 65,1 98 , 6
Sek. Sek. Sek . Sek. Sek . Sek .
Verfahren direkt direkt direkt direkt RWTS RWTS
1 1 1 1 2 2
Pass Pass Pass Pass Pass Pass
"Lesegeschw. 23 , 4 17,2 17,3 20,4 17,3 17 , 3
Sek. Sek. Sek. Sek. Sek. Sek.
Beim Testen verschi ede ner Kopierprogramme fiel mir auf, daß sich die Ko pien unterschied lich gut lesen li eßen. Um zu meßbaren Ergebnissen zu kommen , ben utzte ich ein Assembler-Programm, daß alle Tracks von 0 bis 34 ($22) einliest. Auf jedem Track wird zunächst Sektor 0 und dann fortlaufend bis Sektor 15 ($F) gelesen, bevor zum nächsten Track gegangen wird . Es wird die Zeit gestoppt, die vom Lesen des ersten bis zum letzten Sektor der Diskette vergeht. Die Ergebn isse finden Sie in der ob igen Tabell e unter "Lesegeschwindigkeit". Hier wird ganz deutlich , daß Locksmith aus dem Ra hmen fä llt und auch COPY IIplus-Produkte noch merklich langsamer gelesen werden als die übrigen Kopien. Zunächst hatte ich die pauschale GAP-Verteilung von Locksm ith (siehe 11.1) in Verdacht, aber dann hätten sich auch Superq uick-Kopien schlecht lesen lasse n müssen. Des Rätsels Lösung fand sich schließlich in der "Sync-Signature". Dam it ist der Versatz der Tracks gegeneinander gemei nt. Wen n Sie Sektor $0 ei nes Tracks gelesen haben, gehen Sie sofort einen Track weiter nach innen und lesen den nächsten vorbeikommenden Sektor. Je nach Track-Versatz (Sync-Signature) kann das ein beli eb iger Sektor von $0 bis $F sein. Es läßt sich leicht zeigen, daß Disketten am schnellsten gelesen werden können, wenn ihre Tracks gegeneinander um -2 versetzt sind , d.h. nach Sektor $0 wird als nächstes der Sektor $E gelesen. Auch ein Wert von -3 ist fast ge nauso gut (Sektor $D). Den Zusammenhang zwischen Sync-Signatur und Lesegeschwindi gkeit finden Sie in der folgenden Grafik:
11
11.4 Das wirbelnde Byte: Byte-B lizzard
237
Sec 24
L e
s e
22
Z 20 e
18
I I
I
~ -8 -7 -6 -5 -4 -3 -2 -1
0
1
2
3
4
5
6
7
8
Sync - Signature Abb . 13 : Lesezeit pro D iskette in Ab hängigkeit von der Sync-Signature
D ie Kopier- und Formatierprogramme benutzen folgende Sync-Sign ature:
Programm DOS 3.3 ProDOS 1. 0 . 2 CP/M 2.2 USCD PASCAL COPYA COPY IIE Byte-Blizzard Superquick COPY IIplu s Locksmith 5.0
Sync-Si gnature -3 -2 -3 -3 -3 -3 -3
-3 (z.T. -2) +7 -1
Die Entwick le r vo n Locksmith scheinem diesem Aspekt ke ine Bedeutung beigemessen zu haben , denn sie wählten den schlechtestmögli che n Wert für ihr Programm a us. Superqu ick li egt genau zwische n - 2 und - 3, sodaß kleine Schwankungen der Diskettendrehzahl zu unterschiedlichen Ergebni ssen füh ren , die aber beide gute Leseergebnisse nac h sich zie he n. "Byte-Blizzard" ist meines Wissens der erste Schnell kopierer für den Apple , dessen Quellcode ga nz veröffentli cht wird. Der Q uellcode ist so umfangreich , daß es nicht mehr mitsamt den Ko mm e ntaren in den Asse mbler ASSESSOR paßt. Benutzen Sie das H ilfs progra mm KOMMEX , um eine "abgespeckte" Version zu erhalten. Sie können "Byte-Blizzard " als Anregung für Modifikatione n ne hme n. We nn Sie me hr oder weniger Speicher habe n , ist "Byte-Blizzard" leicht anzupassen.
238
11 . Schne ll wie der Wind
Auch Disketten mit bis zu 80 Track machen keine Schwierigkeiten. Lediglich 160-Track Disketten mit altenativer Spurumschaltung (Erphi-Contro ll er) erfordern größere Maßnahmen. Aber ansieh sollten Sie jetzt vor keinem Problem in Assembler mehr zurückschrecken.
BYTE-BLIZZARD 1
2 3
4 5 6 7
8 9
10 11
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
;******************************* Byte-Blizzard Version 1.0 von Dr. Jürgen B. Kehrel Dezember 1985
* * *
;******************************* Schne ll e Lese- (READ16) und Schreibroutinen (WRTRK ) in Anlehnung an Locksmi t h 5 .0 RDADR16 und SEEKABS sowie SUET und LUET nach DOS 3.3 Zero-Page Spe i cherstel l en SLOTI DRIVEI SLOT2 DRIVE2 TEMP I NDEX CHKSUM SEKTOR SYNCS CH PTR SPURIST SPURSOLL
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
$0006 $0007 $0008 $0009 $00 17 $0018 $00 19 $OO lE $OO lF $0024 $OOCE $OO EB $OO EC
;+$OOC F
; Reset-Vektor, Bildschirm SOFTEV ZEI LE14
EQU EQU
$03F2 $072A
; Tabellen zum Lesen RDTRANSI EQU RDTRANS2 EQU RDTRANS3 EQU
$0300 $0340 $0380
; Tabe llen zum Sc hreiben WRTRANSI WRTRANS2 WRTRANS3 WRTRANS4
EQU EQU EQU EQU
$0800 $0900 $OAOO $OBOO
Beginn des Datenpuffers
239
11.4 Das wirbelnde Byte: Byte-Blizzard
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
PUF'F'ER
EQU
$2000
; Tastatur KEY STROBE
EQU EQU
$COOO $COI0
; Apple //e , c 80-Zeichenkarte STR800F'F' EQU COL800F'F' EQU
$COOO $COOC
; Softswitches ROM LCRAMB2
EQU EQU
$C082 $C083
; Grundadressen Disk-Contro11er PHASEOOF' MOTOROF'F' MOTORON DRVIENAB DRV2ENAB DATASTRB LOADDATA INPUTMOD OUTMODUS DSTRBSL6 LDATASL6 INPMDSL6
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
$C080 $C088 $C089 $C08A $C08B $C08C $C08D $C08E $C08F' $COEC $COED $COEE
; RAM-Karte CARDOF'F' BANK
EQU EQU
$CF'F'F' $DOOO
; Monitor-ROM TEXT TABV BELL HOME CLREOL RDKEY CROUT COUT1 SETINV SETNORM SETKBD SETVID RESET
EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU EQU
$F'B2F' $F'B5B $F'BDD $F'C58 $F'C9C $F'DOC $F'D8E $F'DF'O $F'E80 $F'E84 $F'E89 $F'E93 $F'F'F'C
240
11. Schnell wie der Wind
OCOO: 4C 00 10
OC03: OC05: OC08 : OCOB: OCOO: OCI0 :
OC13: OC15: OC18: OCIB: OCI0: OCIF: OC22: OC25: OC28: OC29:
A6 BO BO 10 BO 4C
A9 90 10 AO 00 20 80 00 88 00
08 80 8E 06 8C 19
FF 8F 8C 70 00 E4 EO EC
CO CO CO 16
CO CO 00 CO CO
F4
OC2B: 20 E7 00
OC2E: OC30: OC32: OC35: OC38: OC39: OC3C: OC30: OC3F: OC40: OC43: OC46 : OC49: OC4C: OC4F OC52 OC55 OC58
84 A9 80 00 98 00 AA A9 EA 8E 8E 8E 8E 8E 80 00 8E 8E
lE FF EO CO EC CO 32 OF FF 6F 75 7B 19 28 EO EC 31 40
OC OC OC 00 00 CO CO 00 00
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
$0300 - $03BF und $0800 - $OBFF mit Tabellen belegt, die vom Programm erzeugt werden. ORG
$OCOO
KALTSTRT JMP
START
Schreiben eines Tracks WRTRK
LOX LOA LOA BPL LOA JMP
SLOT2 LOAOOATA,X INPUTMOO, X WRSYNC OATASTRB,X WPROT
;Slot Copy ;Write-P rotected? ;Nein, we it er ;Ja ;zurück
viele Sync-Bytes schreiben WRSYNC
LOA STA ORA LOY BNE SYNCLOOP J SR WRSI STA WRS2 ORA OEY BNE JSR
UFF OUTMOOUS,X OATASTRB,X U70 SYNCLOOP WAIT27 LOATASL6 OSTRBSL6
GAP 1
;Write/Load ;Latch
SYNCLOOP
;36 Takte ;40 ;schreiben 4 ;6 ;9 (8)
WAIT23
;31
Seiteneins tie g für GAP 3 Adressen modifiz. je nach Sektor SYNCBYTE STY LOA WRS3 STA WRS4 ORA TYA ORA TAX LOA NOP STX STX STX STX STX WRS5 STA WRS6 ORA STX STX
SEKTOR UFF LOATASL6 OSTRBSL6 STORE UFF SYB1+2 SYB2+2 SYB3+2 ZPLl+2 ZPL2+2 LOATASL6 OSTRBSL6 ZPL3+2 ZPL4+2
;34 ;36 ;40 ;schreiben ;6 ;10 ;12 ;14 ;16 ;20 ;24 ;28 ;3 2 ;36 ;40 ;4 ;8 ;12
241
11.4 Das wirbelnde Byte: Byte-Blizzard OC5B : OC5E: OC61: OC64: OC67 : OC6A :
OC60: OC70: OC73: OC76: OC79: OC7C: OC7F': OC82: OC83: OC85: OC88:
OC8B: OC80: OC8E: OC9 1 : OC94: OC97: OC98:
OC9A: OC9C: OC9F': OCAI : OCA4: OCA6:
OCA9: OCAC: OCAF': OCB2 : OCB5: OCB7: OCB9: OCBC: OCBF': OCC2: OCC4:
8E 8E 8E 20 80 00
AE BO AE 10 AE 10 80 EA A9 80 00
A4 EA 20 80 00 88 00
A9 20 A9 20 A9 20
AO 20 AO 20 85 A5 20 AO 40 45 48
49 5B 71 EC EO EC
54 00 A9 00 F'E 00 31
00 00 00 00 CO CO
20 08 20 09 20 OA OF'
F'F' EO CO EC CO
IF' E4 00 EO CO EC CO F'4
05 07 00 AA 08 00 96 08 00
3B BO 36 BO 17 lE BE 3B 36 lE
OF' 00 OF' 00 00 OF' OF'
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
WRS7 WRS8
STX STX STX J SR STA ORA
ZPL5+2 ZPL6+2 LAST+2 WAITRTS LOATASL6 OSTRBSL6
;16 ;20 ;24 ;36 ;40 ;4
1. Byte zum Schreiben vorbere i ten
SYBl SYB2 SYB3
WRS9 WRSI0
LOX LOA LOX ORA LOX ORA STA NOP LOA STA ORA
PUF'F'ER+$54 WRTRANSl,X PUF'F'ER+$A9 WRTRANS2,X PUF'F'ER+$F'E WRTRANS3 , X NIBBTEMP U F'F' LOATASL6 OSTRBSL6
;8 ; 12 ;16 ;20 ;24 ;28 ;32 ;34 ;36 ;40 ;4
Spurspezifische Anzahl von Synchronisations- Bytes LOY NOP GAPISYNC JSR WRS11 STA WRS12 ORA OEY BNE
SYNCS WAIT27 LOATASL6 OSTRBSL6 GAPISYNC
;Anzah l (7) ;9 ;36 ;40 ;4 ;6 ;9 (8)
Adressfeld-Prolog schre ib e n LOA JSR LOA J SR LOA JSR
U 05 WBYTE16 UAA WBYTE14 t$96 WBYTE14
; 10 ;letztes F'F' kein Sync ;12 ;18+14=32 ; 12 ; 18+14=32
Adress-Bytes (VOL, TRK, SEC, CHK) LOA JSR LOA JSR STA LOA JSR LOA EOR EOR PHA
RVOL WROOOEVE TRACKC WROOOEVE TEMP SEKTOR WROOOEVI RVOL TRACKC SEKTOR
; 14 ;20+12=32 ; 14 ; 20+12=32 ;13 Anpassung ;16 ;22+10=32 ;14 ;18 ;21 ;24 merken
242 OCC5 OCC6 OCC8 OCCB: OCCE: OCCF: OCOl:
OC04 : OC06: OC09: OCOB: OCOE : OCEO :
11. Schnell wie der Wind 4A 09 80 00 68 09 20
A9 20 A9 20 A9 20
AA EO CO EC CO AA
07 00
OE 08 00 AA 08 00 EB 08 00
OCE3 : OCE4 : OCE5: OCE6: OCE7 : OCE9: OCEB:
EA EA 48 68 AO 07 A9 FF 00 03
OCEO: OCFO: OCF3: OCF6: OCF7:
20 80 00 88 00
OCF9: OCFB: OCFE: 0000: 0003: 0005:
A9 20 A9 20 A9 20
E4 00 EO CO EC CO F4
05 03 00 AA
08 00 AO 08 00
0008: OOOB: OOOE: 0011 : 0013:
AE BO 20 AO EA
31 OF 00 OB OB 00 54
0014: 0017: 001A: 0010 :
EE BE BO 80
30 00 00 EO
OF 20 OB CO
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
WRS13 WRS14
LSR ORA STA ORA PLA ORA JSR
U AA LOATASL6 OSTRBSL6 UAA WBYTE16
;26 ;28 ;32 ;4 ;8 zurück ; 10 ;16+16=32
Adressfe l d-Epilog schreiben LOA JSR LOA JSR LOA JSR
UOE WBYTE14 UAA WBYTE14 U EB WBYTE14
;12 ;18+14=32 ; 12 ;18+14=32 ;12 ; 18+14=32
7 Sync-Bytes GAP 2 NOP NOP PHA PLA LOY LOA BNE GAP2LOOP J SR GAP2 STA WRS15 ORA OEY BNE
U07 UFF GAP2 WAIT27 LOATASL6 OSTRBSL6
; 12 Tak te ;14 ;17 ;21 ;23 ;25 ;28 ; (32)
GAP2LOOP
Oatenfeld-Prolog schreiben LOA JSR LOA J SR LOA J SR
U05 WBYTE24 UAA WBYTE14 UAO WBYTE14
;alle FF ' s Sync
Oie 342 Oaten-Nibble schreiben
ZAPLOOP ZPLI WRS16
LOX LOA JSR LOY NOP
NIBBTEMP WRTRANS4,X WBYTE8 U 54
;vorab kodiert ; 18 ;24+8=32 ;12 ;14 Anpassung
INC LOX LOA STA
OUMMY PUFFER,Y WRTRANS4,X LOATASL6
20 Anpassu ng 24 28 32
11.4 Das wirbelnde Byte: Byte-Blizzard 0020: 0023: 0026: 0029: 002C: 002F: 0032: 0035: 0038: 003B: 003E: 0041 : 0044: 0047: 004A: 0040: 0050: 0053: 0054: 0056: 0059: 005C: 005F: 0060: 0061 : 0064: 0067: 006A: 006B: 006C:
00 AO BE BO 80 BE BO 80 00 AO BE 10 80 BE BO 80 00 88 30 AO BE 10 AA EA BO 80 00 48 68 4C
EC 31 A9 00 31 55 00 EO EC 31 54 00 31 AA 00 EO EC
006F: 0072: 0075: 0078: 007A: 007B: 007C: 007E: 007F: 0082: 0085: 0088: 0089: 008B: 008C: 008F:
AE BO 20 A5 OA A8 BI AA BO 80 00 C8 BI AA BO 20
FF 20 00 OB 00 00 lE
0092 0094 0097 0099
A9 20 A9 20
CO OF 20 OA OF 20 OB CO CO OF 20 09 OF 20 OB CO CO
19 31 OF 00 20 00 08 00 OB EO CO EC CO 14 00
CE 00 OB EO CO EC CO CE 00 OB 00 00
OE 08 00 AA 08 00
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319
WRS17 ZPL2 ZPL3 WRS18 WRS19 ZPL4 ZPL5 WRS20 WRS21
ZPL6
WRS22 WRS23
LAST
WRS24 WRS25
243
ORA LOA LOX LOA STA LOX LOA STA ORA LOA LOX ORA STA LOX LOA STA ORA OEY BMI LOA LOX ORA TAX NOP LOA STA ORA PHA PLA JMP
OSTRBSL6 ;4 NIBBTEMP ;8 PUFFER+$A9,Y ;12 WRTRANS3 , X ;16 NIBBTEMP ;20 PUFFER+$55,Y ;24 WRTRANS4 , X ;28 LOATASL6 ;32 OSTRBSL6 ;4 NIBBTEMP ;8 PUFF'ER+$54,Y ;12 WRTRANS2,X ; 16 NIBBTEMP ;20 PUFFER+$AA,Y ;24 WRTRANS4,X ;28 ;32 LOATASL6 OSTRBSL6 ;4 ;6 LAST ;8 (9) NIBBTEMP ; 12 PUFFER ,Y ;16 WRTRANSl , X ;20 ;22 ;24 Anpassung WRTRANS4,X ;28 LOATASL6 ;32 OSTRBSL6 ;4 ;7 Anpassung ;11 dito ZAPLOOP ;14
LOX LOA JSR LOA ASL TAY LOA TAX LOA STA ORA INY LOA TAX LOA JSR
PUFFER+$FF WRTRANS4 , X WBYTE9 SEKTOR
;13 ;17 ;23+9=32 ;13 ; 15 ;17 (PTR), Y ;1. Extrabyte (22) ;24 WRTRANS4 , X ;28 LOATASL6 ;32 OSTRBSL6 ;4 ;6 (PTR) , Y ; 2. Extrabyte ( 1 1 ;13 WRTRANS4 , X ;17 WBYTE9 ;23+9=32
Oatenfeld-Epilog schreiben LOA JSR LOA JSR
UOE WBYTE14 UAA WBYTE14
12 18+14=32 12
244
11. Schnell wie der Wind
OD9C OD9E ODAl ODA3 :
A9 20 A9 20
ODA6: ODA9: ODAB: ODAC : ODAE : ODBO: ODB2:
EE C8 CO BO 84 4C
ODB5: ODB6: ODB9 : ODBC :
EA AD OD 60
ODBD: ODBE: ODBF : ODCO: ODC2: ODC5: ODC8: ODC9: ODCB: ODCD :
EA AA 4A 09 8D OD 8A 09 85 4C
A4
ODDO: 4C ODD3: ODD6: ODD7: ODD8 : ODDB : ODDC: ODDD: ODEO: ODE3:
EE EA EA EE EA EA 8D OD 60
ODE4: 80 ODE7: 48 ODE8: 68
EB LDA U EB 320 D8 OD 32 1 JSR WBYTE14 FF 322 LDA U FF D8 OD 323 J SR WBYTE14 ;Übergang 324 Prüfen , ob alle Sektoren geschr ieben 325 326 INC DUMMY ; 16 30 OF 327 lE LDY SEKTOR ; 19 328 ;21 INY 329 10 CPY U IO ;23 330 05 33 1 BCS TRKREADY ;25 (26) lE STY SEKTOR ;28 332 2E OC 333 JMP SYNCBYTE ;3 1 334 Trackfertig, Read, Sch l euse normal. 335 336 337 TRKREADY NO P EE CO 338 WRS26 LDA INPMDSL6 EC CO 339 WRS27 ORA DSTRBSL6 340 RTS 341 342 Schreibe Byte Odd-Even Codiert 343 344 WRODDEVE NOP 345 WRODDEV l TAX 346 LSR AA 347 ORA UAA ED CO 348 WRS28 STA LDATASL6 EC CO 349 WRS29 ORA DSTRBSL6 TXA 350 AA 35 1 ORA U AA 17 STA TEMP 352 D6 OD 353 JMP WBYTE1 8 354 Zeitverzögerung, dann schreiben 355 356 DC OD 357 WBYTE9 JMP WBYTE6 358 30 OF 359 WBYTE24 I NC DUMMY 360 WBYTE1 8 NOP 361 WBYTE16 NO? 30 OF 362 WBYTE14 INC DUMMY NOP 363 WBYTE8 364 WBYTE6 NO? STA LDATASL6 ED CO 365 WRS30 EC CO 366 WRS3 1 ORA DSTRBSL6 RTS 367 368 Zeitverzögerungen 369 370 STA DUMMY 30 OF 371 WAI T27 PHA 372 WAIT23 PLA 373
11.4 Das wirbelnde Byte: Byte-Blizzard ODE9: 8D 30 OF ODEC: 60
245
374 STA DUMMY 375 WAITRTS RTS 376 377 378 Merkbereich für Sektoren 379 DFS $10 380 SIM 381 Daten lesen, Puffer immer auf 382 Seitengrenze, Hi-Byte wird übergeben 383 384 X-Reg muß Slot*16 enthalten 385 LDA ZIELHI ODFD: AD 33 OF 386 READ16 OEOO: 8D 56 OE 387 STA RDNl+2 OE03: 8D 6A OE 388 STA RDN2+2 OE06 : 8D 7E OE 389 STA RDN3+2 OE09: 8D C4 OE 390 STA RDDl+2 391 Datenfeld lesen 32 Versuche 392 393 OEOC: AO 20 394 RDDAPROL LDY U20 DEY OEOE: 88 395 RDVERS OEOF: 10 02 BPL DAPROLI 396 OEll : 38 SEC 397 ;Fehl erausstieg OE12 : 60 RTS 398 399 400 Datenfeld-Prolog suchen 401 OE13: BD 8C CO 402 DAPROLI LDA DATASTRB,X OE16: 10 FB 403 BPL DAPROLI OE18: 49 D5 404 RDPROL2 EOR UD5 OEIA: DO F2 405 BNE RDVERS OEIC: EA 406 NOP OEID: BD 8C CO 407 RDPROL3 LDA DATASTRB,X OE20: 10 FB 408 BPL RDPROL3 OE22: C9 AA 409 CMP UAA OE24: DO F2 410 BNE RDPROL2 OE26: EA 411 NOP OE27: BD 8C CO 412 RDPROL4 LDA DATASTRB,X OE2A: 10 FB 413 BPL RDPROL4 OE2C: C9 AD 414 CMP UAD OE2E: DO E8 415 BNE RDPROL2 416 417 Disk-Nibble lesen und ab l ege n 418 OE30: AD 39 OF 419 LDA RSEC Index im ZusatzOE33: OA 420 ASL Puffer für die 2 OE34: 85 18 421 STA INDEX "Extrabytes" OE36: 24 17 422 BIT TEMP OE38: AE EC CO 423 RDNIBBL LDX DSTRBSL6 OE3B: 10 FB 424 BPL RDNIBBL OE3D: BD 00 OF 425 LDA LUET-$96,X OE40: 85 17 426 STA TEMP OE42: 85 19 427 STA CHKSUM
246 OE44: OE46: OE47: OE4A: OE4C: OE4F: OE51: OE54: OE57: OE59: OE5B: OE5E: OE60: OE63 : OE65 : OE68: OE6B: OE6D: OE6F: OE72: OE74: OE77: OE79: OE7C: OE7F : OE81: OE83: OE86: OE88: OE8B: OE8D: OE8F: OE91: OE92: OE94: OE96: OE99: OE9B: OE9E: OEAO: OEA2: OEA4: OEA6: OEA8: OEAB: OEAD: OEBO: OEB1: OEB3: OEB5:
11. Schnell wie der Wind AO EA AE 10 BD A6 ID 99 45 85 AE 10 BD A6 ID 99 45 85 AE 10 BD A6 ID 99 45 85 AE 10 BD 85 45 85 88 10 24 AE 10 BD A4 91 45 29 85 AE 10 BD C8 91 C5 DO
54 EC FB 00 17 00 00 19 19 EC FB 00 17 40 55 19 19 EC FB 00 17 80 AA 19 19 EC FB 00 17 19 19 B3 17 EC FB 00 18 CE 19 3F 19 EC FB 00
CO OF 03 20 CO OF 03 20 CO OF 03 20 CO OF
CO OF
CO OF
CE 19 IB
OEB7: AE EC CO
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
RDNIBBLl
RDNl RDNIBBL2
RDN2 RDNIBBL3
RDN3 RDNIBBL4
RDNIBBL5
RDNIBBL6
LDY NOP LDX BPL LDA LDX ORA STA EOR STA LDX BPL LDA LDX ORA STA EOR STA LDX BPL LDA LDX ORA STA EOR STA LDX BPL LDA STA EOR STA DEY BPL BIT LDX BPL LDA LDY STA EOR AND STA LDX BPL LDA INY STA CMP BNE
U 54 DSTRBSL6 RDNIBBLl LUET-$96 , X TEMP RDTRANS1, X PUFFER,Y CHKSUM CHKSUM DSTRBSL6 RDNIBBL2 LUET-$96 , X TEMP RDTRANS2 , X PUFFER+$55,Y CHKSUM CHKSUM DSTRBSL6 RDNIBBL3 LUET-$96,X TEMP RDTRANS3 , X PUFFER+$AA , Y CHKSUM CHKSUM DSTRBSL6 RDNIBBL4 LUET-$96,X TEMP CHKSUM CHKSUM RDNIBBLl TEMP DSTRBSL6 RDNIBBL5 LUET-$96,X INDEX (PTR), Y ;l. Extrabyte CHKSUM U 3F CHKSUM DSTRBSL6 RDNIBBL6 LUET-$96 , X (PTR) , Y CHKSUM RDERROR
Datenfeld-Epilog lesen RDDAEPIL LDX
DSTRBSL6
; 2. Extrabyte
11.4 Das wirbelnde Byte: Byte-Blizzard
OEBA : OEBC: OEBE: OECO: OEC2: OEC5: OEC7: OECA : OECC : OECE : OEOO: OEO I :
10 EO 00 A5 80 24 AE 10 EO 00 18 60
FB OE 12 17 FF 20 17 EC CO FB AA 02
OE02: 38 OE03 : 60
OE04 : OE06: OE08: OE09: OEOB:
omo:
AO 84 C8 00 E6 FO
OEOF: OEE2: OEE4: OEE6: OEE8 : OEE9 : OEEC: OEEE: OEFO: OEF2: OEF4: OEF7: OEF9: OEFB:
BO 10 C9 00 EA BO 10 C9 00 AO BO 10 C9 00
OEFO: OEFF : OFOl : OF04: OF06: OF07: OF09: OFOC: OFOE : OFI0:
A9 85 BD 10 2A 85 BD 10 25 99
FC 17 04 17 F3 8C CO FB 05 FO 8C CO FB AA
F2 03 8C CO FB 96 E7
00 19 8C CO FB 17 8C CO FB 17 38 OF
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
BPL CPX BNE LOA ROOl STA BIT ROOAEPIl LOX BPL CPX BNE CLC RTS ROERROR
247 ROOAEPIL UOE ROERROR TEMP PUFFER+$FF TEMP OSTRBSL6 ROOAEPIl UAA ROERROR
SEC RTS
Adressfeld lesen Adressfeld-Prolog suchen X muß Slot*16 enthalten! ROAOR16 VERSUCH
RAPROL RAPROLl RAPROL2
RAPROL3
LOY STY INY BNE INC BEQ
UFC TEMP
LOA BPL CMP BNE NOP LOA BPL CMP BNE LOY LDA BPL CMP BNE
OATASTRB,X RAPROL U05 VERSUCH
;Versuchszahl
RAPROL TEMP ROERROR
OATASTRB, X RAPROL2 UAA RAPROLl ;4 Bytes U03 OATASTRB,X RAPROL3 U96 RAPROLl
Adressfeld lesen , Bytes zusammensetzen ADRLOOP ADRI
ADR2
LOA STA LDA BPL ROL STA LDA BPL AND STA
;Chksum init. U OO CHKSUM DATASTRB,X ADRI TEMP DATASTRB , X AOR2 TEMP AORINFO.Y ;Werte merken
248 OF13 OF15 OF16
11. Schnell wie der Wind
45 19 88 10 E7
OF18: A8 OF19: DO B7
OFIB: OFIE: OF20: OF22: OF24: OF25: OF28: OF2A: OF2C: OF2E: OF2F:
OF30: OF31: OF32: OF33: OF34: OF35: OF36: OF37: OF38: OF39: OF3A: OF3B: OF3C: OF3D:
OF3E: OF40: OF42: OF45: OF47: OF48: OF4A: OF4B: OF4D: OF4F: OF51:
BD 10 C9 DO EA BD 10 C9 DO 18 60
8C CO FB DE AE 8C CO FB AA A4
00 00 00 00 00 00 00 00 00 00 00 00 00 00
A9 85 AD AO OA 26 88 DO 85 A9 65
00 CF 34 OF 05 CF FA CE lE CF
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
EOR DEY BPL
CHKSUM ADRLOOP
TAY BNE
RDERROR
;Chksum muß 0 sein
Adressfeld-Epilog l ese n RAEPIL
RAEPIl
LDA BPL CMP BNE NOP LDA BPL CMP BNE CLC RTS
DATASTRB , X RAEPIL #$DE RDERROR DATASTRB,X RAEPIl #$AA RDERROR
Variablen-Liste DUMMY NIBBTEMP STORE ZIELHI TRACK TRACKO TRACKC TRKPOS ADRINFO RSEC RTRK RVOL RDVER WRVERS
HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX HEX
00 00 00 00 00 00 00 00 00 00 00 00 00 00
(PTR) auf Merkbereich für 2 Zusatzbytes für jeden gelese nen Sektor zeigen lassen 32 ($20) Bytes pro Track erforderlich MERK
MLOOP
LDA STA LDA LDY ASL ROL DEY BNE STA LDA ADC
#$00 PTR+l TRACK #$05
; Hi- Byte ;Track im Durchgang ,. ,. 32
PTR+l
;Übertrag
MLOOP PTR #$ lE PTR+l
Lo-Byte $l EOO- $lFFF bei max. 16 Tracks
11.4 Das wirbelnde Byte: Byte-Blizzard OF53 : 85 CF OF55: 60
0F'56: OF59: OF5E: OF61: OF66: OF69 : OF6E : OF71: OF76: OF79: OF7E: OF81: OF86 : OF89: OF8E: OF9 1 :
96 9B A7 AO B4 B7 BO CB 06 OA OF E7 EO F2 F7 FB
97 90 AB AE B5 B9 BE CO 07 OB E5 E9 EE F3 F9 FC
9A 9E AC AF B6 BA BF CE 09 OC E6 EA EF F4 FA FO
OF96 : OF99: OF9E : OFAl : OFA6: OFA9: OFAE: OFBl: OFB6: OFB9: OFBE: OFCl: OFC6: OFC9: OFCE: 0F'01 : 0F'06: OF09: OFOE: OFEl: OFE6: OFE9: OFEE: OFFl: OFF'6: OFF9 :
00 FF 05 FF 07 FF OC FF 12 14 19 FF FF FF 10 FF 20 22 27 FF 2A 2C 31 F'F' 37 39
01 02 06 FF 08 FF 00 OE 13 15 lA FF FF FF lE FF 21 23 28 FF 2B 20 32 33 38 3A
FF 03 FF FF FF 09 FF OF FF 16 FF FF FF IB FF IF FF 24 FF FF FF 2E FF 34 FF 3B
STA PTR+l 590 591 RTS 592 593 594 Schreib-Übe r se tzungst abelle SÜT 595 HEX 96979A9B909E9FA6 596 SUET 9F A6 597 HEX A7ABACAOAEAFB2B3 B2 B3 HEX B4B5B6B7B9BABBBC 598 BB BC HEX BOBEBFCBCOCECF03 599 CF' 03 HEX 0607090AOBOCOOOE 600 00 OE HEX OFE5E6E7E9EAEBEC 601 EB EC HEX EOEEEFF2F3F4F5F6 602 F5 F6 HEX F7F9FAFBFCFOFEFF 603 FE FF 604 Le s e-Übersetzun gstabelle 605 Un gültige Oi s kb ytes = FF 606 indiziert zur Basis LUET- $96 607 muß auf $xx96 beginnen! 608 609 HEX 0001FFFF0203FF04 610 LUET FF 04 611 HEX 0506FFFFFFFFFFFF FF FF 612 HEX 0708FFFFFF090AOB OA OB HEX OCOOFFFFOEOFIOll 613 10 11 614 HEX 1213FF1415161718 17 18 HEX 191AFFFFFFFFFFFF 615 FF FF 616 HEX FFFFFFFFF'FIBFF'lC FF l C 617 HEX 101EFFFFFFIFFFFF FF FF 618 HEX 2021FF2223242526 25 26 619 HEX 2728FFFFFFFFFF29 FF 29 HEX 2A2BFF2C202E2F30 620 2F 30 HEX 3132FFFF33343536 621 35 36 HEX 3738FF393A3B3C30 622 3C 30
249
11. Schnell wie der Wind
250 OF'F'E: 3E 3F'
1000 : 1003: 1006: 1009: 100C:
100F' : 1012: 1015: 1018: 10lA: 101D : 1020: 1022: 1024: 1027: 102A: 102C: 102D: 1030: 1033 : 1035: 1038:
103B: 103D: 1040: 1043: 1045 : 1048: 104B: 104D:
1050 1053 1056 1059 105C 105F 1062 106A 1072
8D 8D 8D 20 20
AD AD AD 49 8D CD DO A9 8D CD DO OA OE 4D F'O AD 4C
A9 8D 8D A9 8D 8D 49 8D
AD 20 20 20 20 C2 C5 D2 C9
00 OC F'F' 2F' BB
CO CO CF' F'B 17
83 83 00 F'F' 00 00 13 55 00 00 09
CO CO DO
00 00 06 82 D4
DO DO
50 F'C F'2 10 F'D F3 A5 F4
82 89 93 58 8A D9 AD C4 CF
DO DO DO DO
CO 15
F'F' 03 FF 03 03
CO FE FE FC 15 D4 C2 AO CE
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 CC C9 AO D6 AO BI
HEX
3E3F'
Ini tialisieren, Tabellen a nl ege n START
STA STA STA JSR JSR
STR800F'F' COL800F'F' CARDOF'F' TEXT MAKETABS
;80-Zeichen aus (IIefc) ;Zusatz-ROMs aus
Teste, ob Lang uage Card vorhanden
NOTLC
LDA LDA LDA EOR STA CMP BNE LDA STA CMP BNE ASL ASL EOR BEQ LDA JMP
LCRAMB2 LCRAMB2 BANK UF'F' BANK BANK NOTLC U55 BANK BANK NOTLC BANK BANK LCOK ROM LCERROR
;RAM-Read Bank 2 ;RAM-Write Bank 2 ;1. Byte der Karte ; invertieren ;zurückschreiben ;ist es verändert? ;kei ne Karte da ; %0101 0101 ;wieder gl eich?
;Ja, also Karte da ;ROMs ein ;F'e hl er, keine LC da
Reset-Vektor in der Seite 3 und in der LC zum Warmstart umsetzen LCOK
LDA STA STA LDA STA STA EOR STA
1f< WRMSTART RESET SOF'TEV 1f> WRMSTART RESET+l SOFTEV+l UA5 SOF'TEV+2
Warmstart WRMSTART LDA ROM JSR SETKBD JSR SETVID JSR HOME JSR PRINT4 ASC "BYTE-BLIZZARD DA DA Cl C5 D2 D3 AE BO AO
;ROM's e in
VERSION 1.0 ( 16 SEKTOREN)"
11.4 Das wirbelnde Byte: Byte-Blizzard 107A: 1082: 1087: 108A : 1092 : 109A: 10A2 : 10AA : 10Af : 10B2: 10B5: 10B7: 10B9: 10BB: lOBE : 10C l : 10C4 : 10C6 : 10C8 : 10CB : 10CE : 10Dl : 10D2 : 10D5 : 10DD: 10E5: 10ED : 10f5: 10f7: 10f8 : 10fB : 1103 : 110B: 1113 : l l1B : 111D: 1120 : 1123 : 11 2B: 1133 : 113B: 1143: 1146: 1147: 114A: 11 52 : 115A: 1162 : 116A : 116D: 116E : 1171 : 1179 : 1181 :
A8 Cf A8 AO D2 C5 CC CC 20 20 85 A5 85 20 20 20 AO A9 20 D4 C3 8D AO BO BO Bl B2 B3 8D AO Bl B9 B7 B5 B3 8D AO AD AD AD AD AD 8D AO BD AO D2 DO C6 8D AO BD C9
Bl D2 C3 Bl AE CE AC C2 B2 Af 07 08 06 C5 B7 20 10 OB 85 D2 CB
B6 C5 A9 B9 AO AO AO C5 15 16
AO BO Bl Bl B2 B3 AO B2 BO B8 B6 B4 8D AD AD AD AD AD AD CC AO D3 C5 AO C5
AO CC AO C9 BD CE
DE AO C3 AA AO
251
AO D3 CE A9 674 B8 B5 CA D5 CB C5 C8 C5 D2 47 675 676 677 678 679 680 681 682 683 684 685 686
JSR JSR STA LDA STA JSR JSR JSR WRMSTRTl LDY LDA JSR ASC
BO BO Bl Bl B2
687 688 BO BO Bl Bl B2 B2 B2 B2
BO Bl B2 B3
ASC BO BO Bl Bl B2 B2 B3 B3
BO B3 Bl B9 B7
689 690 B4 B5 B2 B3 BO Bl B8 B9
B6 B4 B2 BO
ASC B7 B8 B5 B6 B3 B4 Bl B2
8D AD AD AD AD AD AD
691 692 AD AD AD AD AD AD AD AD
AD AD AD AD
ASC AD AD AD AD AD AD AD AD
C5 D3 CE D2
HEX 8D ASC " L = LESEN, S = SCHREIB EN, P CE AC C3 C8 AC AO D5 C5
15 16 17 15 Cl BA
693 694 C5 D3 BD AO C2 C5 AO DO
C5 CB D4 AO C5 C8 C9
DCI " (C) 1985 AO C4 D2 C7 D2 C5 C4 C5
;herüberkopiere n ; Adressen modifiz. ;HTAB ; Zeile 11
HEX 8D 01234567890123456789012345678901234"
8D8D8D
------------------------- ------------ 11
HEX ASC " DO C5 AO AO C8 CC
ORIGNORM SLOTDRl DRIVEl SLOT2 SLOT l COPYNORM SLOTDR2 SLOTMODI U l0 UOB PRINT2 "TRACK:"
HEX 8D 00000000001111111111222222222233333"
HEX
695 AO 696 C9 CD AO D3 C8 C5 D2 AC BD AO C6 C5
DR. JUERGEN KEHREL, HEIDELBERG"
i =
8D IM SPEICHER ,
*=
fE HLER,
PRUEfEN"
GUT"
252 1189: 1191 : 1194: 1195 : 1198: 11AO: 11A8: IlBO: 11B8: 11BB: 11BD: 11CO: 11C8: 11DO: 11D7: 11D9: 11DC: 11E4: 11EC: 11F4 : 11F9: 11FC: 11FF: 1201: 1203: 1205: 1207 : 1209: 120B:
11. Schnell wie der Wind
C5 C7 8D AO AD AD AD AD AD 8D AO C5 CB C9 8D AO CB CE D4 D3 2C 20 C9 FO C9 FO C9 DO 4C
120E: 20 1211 : FO
1213: 1216: 1219: 121C : 121E: 121F: 1220: 1221: 1222: 1224: 1226: 1228: 122A:
20 AD 8D A5 4A 4A 4A 4A 09 85 A9 85 6C
122D : A9 122F : 20 1232: A9
D2 AC AO AE D5 D4 697 AD AD 698 AD AD AD AD AD AD AD AD AD AD AD AD AD AD AD AD AD AD 8D 699 AO C2 700 C9 C4 C5 AO C5 D4 D4 C5 CE CC C5 C7 8D 701 AO A8 702 A9 CF DO C9 AO AO A8 C2 C5 CE AO AO C3 BE AO 3F 10 CO 703 OC FD 704 CB 705 2A 706 C2 707 OC 708 9B 709 03 710 50 10 711 712 DD FB 713 E9 714 715 716 717 58 FC 718 F3 03 719 F4 03 720 06 721 722 723 724 725 CO 726 CF 727 00 728 CE 729 CE 00 730 731 732 733 OE 734 5B FB 735 00 736
AO BD AO HEX AD AD AD AD
ASC AD AD AD AD AD AD AD AD
8D
-------------------------------- - ---- "
HEX ASC
8D8D BEIDE DISKETTEN EINLEGEN"
C4 C9 D3 CE AO C5 C5 CE HEX 8D8D DCI (K)OPIEREN
(B)OOTEN
C5 D2 C5 A9 CF CF AO BC C5 AUSWAHL
SONICHT
BIT J SR CMP BEQ CMP BEQ CMP BNE JMP
STROBE RDKEY *"K" COPY *"B" REBOOT *$9B SON ICHT WRMSTART
JSR BEQ
BELL AUSWAHL
<ESC > 7 11
;Tastendruck ;Kopieren ;Beenden ; <ESC >
;nicht möglich ; immer
Reboot-Routine im aktuel len Slot REBOOT
J SR LDA STA LDA LSR LSR LSR LSR ORA STA LDA STA JMP
HOME SOFTEV+l SOFTEV+2 SLOTl
;Power-Up-Vektor ;zerstöre n *16
*$CO PTR+l *$00 PTR (PTR)
;Sprung z. Controller
Diskettenkopie COPY
LDA JSR LDA
*$OE TAB V *$00
; Zeile 14 ; ab Zeilenbeginn
11.4 Das wirbe lnde Byte: Byte-Blizzard 1234: 1236: 1239: 123B: 123E: 1241 : 1244 : 1246:
85 20 A9 8D 8D 8D A9 85
24 9C 00 37 35 36 16 IF'
1248: 124B: 124E: 1250: 1252: 1255: 1258: 125A: 125D: 125F' : 1261 : 1264 : 1267: 1269:
AD AD A6 A5 20 20 A9 20 A6 A5 20 20 A9 20
83 83 06 07 C9 DF' OA 95 08 09 C9 DF' OA 55
126C: 126E: 1271: 1273: 1275: 1278: 127A: 127D: 127F' : 1281 : 1284: 1286 : 1289 : 128C :
A9 8D A6 A5 20 A9 20 A6 A5 20 A9 20 CE DO
02 94 06 07 C9 OB 95 08 09 C9 OB 55 94 E3
F'C OF' OF' OF'
CO CO 14 14 12 14 14 13 12 14 12 14 13 12
128E: AD 82 CO 1291: 4C C4 10 1294: 00
1295: 1298: 129B: 129E : 12A l : 12M: 12A5 :
8D BD 20 AD 8D OA 85
34 89 6B 35 37 EB
OF' CO 15 OF' OF'
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
STA JSR LDA STA STA STA LDA STA
253 CH CLREOL uOO TRKPOS TRACKO TRACKC #$16 SYNCS
; Zeile l öschen ; ini tialisieren ;Track Origin a l ;Track Copy ;Sy nc für GAP3 auf ; $lA (22+4) setzen
ORIGINAL LDA LDA LDX LDA JSR JSR LDA JSR LDX LDA JSR JSR LDA JSR
LCRAMB2 LCRAMB2 SLOTl DRIVE1 DRVWAHL TRKOPOS #10 READTRKS SLOT2 DRIVE2 DRVWAHL TRKOPOS #10 WRITETRK
;RAM Read Bank2 ;RAM Write Bank2 ;Slot Original ;Drive Original ; Drive anwählen ;auf Spur 0 posit. ; 11 Tracks ;Tracks lesen
LDA STA COPYLOOP LDX LDA JSR LDA JSR LDX LDA JSR LDA JSR DEC BNE
#02 LOOPCNT SLOTl DRIVE1 DRVWAHL #11 READTRKS SLOT2 DRIVE2 DRVWAHL #11 WRITETRK LOOPCNT COPYLOOP
;2 Durchgänge
LDA JMP
ROM WRMSTRTl
HEX
00
LOOPCNT
;Drive anwäh len ;auf Track 0 zurück ;1 1 Track schreiben
;Slot Original ;Drive Original ;D rive anwählen ;12 Tracks/Durchgan g ;T racks lesen ; Dr ive anwählen ;12 Tracks schreiben ; F' ert ig ? ;Nein ;ROM ein ;NEU
Im Akku übergebene Anzahl von Tracks lesen READTRKS STA LDA JSR LDA STA ASL STA
TRACK MOTORON ,X PAUSE TRACKO TRKPOS SPURIST
;Anzahl der Tracks war ten Po s . Original für F'ehleranzeige *2
254 791 792 12A7 AC 34 OF 793 12M B9 FF 17 794 12AD 8D 32 OF 795 12BO 20 3E OF 796 12B3: A9 OC 797 12B5: AC 35 OF 798 12B8: 99 2A 07 799 12BB: A9 50 800 12BD: 8D 3C OF 80 1 802 803 804 805 12CO : A9 FF 806 12C2: AO 10 807 12C4: 88 808 12C5: 99 ED OD 809 12C8: DO FA 810 811 812 813 12CA: 84 lE 814 12CC: A6 06 815 12CE: 20 D4 OE 816 12D l: 90 lC 817 12D3: CE 3C OF 818 1·2D6 : 00 F6 819 820 12D8: AD 82 CO 821 12DB: 20 AF 15 822 12DE: 4C 4F 16 823 824 12El: CE 3C OF 825 12E4: DO E6 826 12E6: AD 82 CO 827 12E9: 20 AF 15 828 12EC: 4C 5C 16 829 830 831 12EF: AD 3A OF 832 12F2: CD 35 OF 833 12F5: DO EI 834 12F7: AC 39 OF 835 12FA: CO 10 836 12FC: BO DA 837 12FE: B9 ED OD 838 1301: FO 00 839 840 1303: 98 1304: OD 32 OF 841 1307: 8D 33 OF 842 843 844 845
11. Schnell wie der Wind
Lesepuffer setzen NXTTRK
LDY LDA STA JSR LDA LDY STA LDA STA
TRACK PUFTAB,Y STORE MERK #$OC TRACKO ZEILE14,Y #$50 RDVER
;Hi-Byte Grundwert ; (PTR) setzen ; L inv ; 5-Mal ; Zähler
Sektormerkbereich FF = Neu , 00 = gelesen
SIMLOOP
LDA LDY DEY STA BNE
#$FF #$ 10 SIM,Y SIMLOOP
;negativ ;16 Sektoren ;Auf negativ set zen ;Merkbereich ;Sch l eife
Sektoren l esen RDSEKTOR STY RDSI LDX READADR JSR BCC TRY DEC BNE
SEKTOR SLOT I RDADR16 ADROK RDVER READADR
;zu lesender Sektor ;S l ot Original ; Adressfeld lesen ;ohne Fehler ;Zah l der Versuche -1 ; neu versuchen
FEHLADR
LDA JSR JMP
ROM ORIGINV ADRFEHL
; ROM ein
DEC BNE LDA JSR JMP
RDVER RDSI ROM ORIGINV DATFEHL
LDA CMP BNE LDY CPY BGE LDA BEQ TYA ORA STA
RTRK TRACKO FEHLADR RSEC #$ 10 FEHLADR SIM,Y TRY
;ge1esener Track ;erwarteter Track
STORE ZIELHI
;Ab1ageort bestimmen
TRYl
ADROK
;Fehlermeldung ausgeben
;Datenfehler
;max. $F ;hatten wir schon
Daten in den Pufferbereich einlesen
255
11.4 Das wirbelnde Byte: Byte-Blizzard 130A: 1300: 130F' : 1312: 1314 : 1317: 1319: 131A: 131C:
131E: 1321 : 1323: 1326: 1328: 1329: 132C: 132F' : 1330: 1331 : 1334: 1337: 1339: 133C: 133E: 1340:
F'O 00 02 39 OF' 00 EO 00 A4 lE C8 CO 10 00 AC
20 BO AC A9 99
AC A9 99 A6 C8 8C 8C 98 OA 20 CE 30 AO C9 F'O 4C
35 OF' DE 2A 07 06 35 OF' 37 OF' EE 34 OA 00 9B 07 A7
14 OF' CO 12
1343 : BD 88 CO 1346: 60
1347 : 134A: 134D: 1350: 1351 : 1352 :
1355: 1358 : 135B: 135E: 136 1 : 1364 : 1365 :
2C 20 AD 68 68 4C
8D BD 20 AD 8D OA 85
10 CO 04 14 82 CO C4 10
34 89 6B 36 37 EB
OF' CO 15 OF' OF'
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
JSR BCS LOY LOA STA LOY INY CPY BNE
REA016 TRYl RSEC #$00 SIM,Y SEKTOR
;Oatenfeld lesen ;F'ehler, nächster Versuch ;Sektor markieren ;auf 00 (positiv) setzen
#$10 RDSEKTOR
;schon 16 ge l esen? ;Nein, also weiter
;nächsten Sektor
nächsten Track lesen
ALLTRK
LDY LDA STA LDX INY STY STY TYA ASL JSR DEC BMI LDA CMP BEQ JMP
TRACKO *"jll ZEI LE14 , Y SLOTI
LDA RTS
MOTOROF'F' , X ;Motor aus
;nächste Spur
TRACKO TRKPOS SEEKABS TRACK ALLTRK KEY #$9B ESCENDE NXTTRK
; *2
; <ESC > ;nächsten Track lesen
vorzeitiger Abbruch ESCENDE
BIT JSR LOA PLA PLA JMP
STROBE MOTOF'F' ROM
;Motoren aus ;h
JSR
WRMSTRTI
Kopie schreiben/verifizieren WRITETRK STA LDA JSR LDA STA ASL STA
TRACK MOTORON , X PAUSE TRACKC TRKPOS SPURIST
Schreibpuffer setzen
;Anzahl Tracks
; *2
256
11. Schnell wie der Wind
1367: 136A: 136D: 1370: 1373: 1375:
AC B9 8D 20 A9 8D
34 F'F' 32 3E 03 3D
1378 : 137A : 137D : 1380 : 1382:
A9 AC 99 A9 8D
13 36 OF' 2A 07 05 3C OF'
OF' 17 OF' OF' OF'
1385: 20 03 OC
1388: A9 10 138A: AC 36 OF' 138D: 99 2A 07
1390: 1392: 1395: 1398: 139B: 139C: 139D: 139E: 139F':
20 20 20 48 68 EA 88 DO
13A l: 13A3: 13A5 : 13A7: 13AA : 13AB:
AO 84 A9 99 88 10
A4
IF' EC OD EC OD EC OD
F'1 OF' lE F'F' ED OD F'A
13AD: A6 08 13AF' : 20 D4 OE 13B2 : BO 31
13B4: AD 39 OF'
90 1 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 93 1 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 95 1 952 953 954
WRNEXT
WRITE
LDY LDA STA J SR LDA STA
TRACK PUF'TAB , Y STORE MERK U03 WRVERS
LDA LDY STA LDA STA
U 13 TRACKC ZEILE14,Y U5 RDV ER
;Hi-Byte Grundwert ; (PTR) setzen ;3 Versuche ;Schreibe n ;wenig Versuche
1 Track formatieren und die Daten des Puffers schreiben JSR
WRTRK
Track verifizieren LDA LDY STA
U I0 ;Prüfe n TRACK C ZEILE14 , Y ;ausgebe n
F'ormatierung der Disk überprüfen. Näc hster l esbarer Sektor muß wieder der erste se in , sonst s ind di e Sync-F'e l der zu l a ng und der Track überschreibt sich selber VF'W
LOESCH
LDY JSR JSR J SR PHA PLA NOP DEY BNE
SYNCS WAI TRTS WAITRTS WA ITRTS
LDY STY LDA STA DEY BPL
UO F' SEKTOR UF'F' SIM,Y
;Pause für GAPI
VF'W ;16 Sek to re n ;auf () 0 initial. ; Zwischenspeicher für ;Sektor nummern
LOESCH
LDX SLOT2 JSR RDADR16 BCS NEUF'ORM
;nächstes Adressfeld ;nicht le sbar
war es der erste Sektor? LDA RSEC
;gelese ner Sektor
11.4 Das wirbelnde Byte: Byte-B lizzard 13B7 : FO 18 13B9: 20 BC 14 13BC: BO 27 13BE: AO 82 CO 13Cl: 4C 38 16
13C4: 13C7: 13C9 : 13CC : 13CF:
20 BO AC B9 FO
04 OE 00 39 OF EO 00 05
1301 : 20 59 14 1304: 90 20 1306 : CE 3C OF 1309 : 00 E9
130B: 130E: 13EO: 13E2 :
13E5: 13E8 : 13EA: 13EO: 13EF: 13F2: 13F4: 13F6: 13F9:
CE FO A9 80
AO FO 20 BO AO C9 00 20 4C
3D OF OE 20 3C OF
36 OF 04 00 39 OF 06 59 78
OF OE OF 14 13
13FC: CE 3C OF 13FF: 00 E9 1401 : FO BB 1403 : AC 39 OF 1406: A9 00 1408: 99 EO 00 140B: C6 lE 1400: 10 B5
955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 99 1 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
257
BEQ JSR BCS
VTRK SYNCZAHL NEUFORM
NOTFOUNO LOA JMP
ROM FORMFEHL
Sektor 0 Syncs verkürzen neu kopieren ; Forma tierung
Ganzen Track lesen , alle Sektoren auf Vol l ständigkeit und Lesbarkeit prüfen JSR BCS LOY LOA BEQ
ROAOR1 6 VVFE RS EC SIM , Y VVFE
VTRK
JSR BCC
VREA016 VOKAY
VVFE
OEC BNE
ROVER ROSEKT
ROSEKT
;Verify-Feh l er ; gefunde ner Sektor ; schon gehabt? ;Ja ;Oaten prüfen
; neuer Versuch
Verify-Fehler OEC BEQ LOA STA
WRVERS NOTFOUNO *$20 ROVER
Das Ende der Spur wird abgewa rtet , dann wird neu format i ert NEUFORM NFORMl
TOWRITE
LOA TRACKC BEQ TOWRITE J SR ROAOR16 BCS NEUF1 LOA RSEC CMP *$O F BNE NEUFI J SR VREA016 JMP WRITE
; le tzter Sektor? ;Oaten l ese n ;Neu schreiben
NEUFI
OEC ROVER BNE NFORMI BEQ NOTFOUNO
VOKAY
LOY RSEC LOA HOO STA SIM,Y
; gelesener Sektor ; markieren
OEC SEKTOR BPL ROSEKT
;nächsten Se kt or ;weiterprüfe n
258
140F : 1411 : 1414 : 1417: 1419: 141C: 141 E: 142 1 : 1423 : 1426:
1428: 142A: 142D: 1430 : 1432 : 1435: 1437 : 1438: 143B : 143 E: 143F : 1440 : 1443: 1446 : 1448: 144B : 144D : 144F:
11. Schnell wie der Wind
A9 8D CE FO 20 BO AD DO 20 BO
A9 AC 99 DO 20 A6 C8 8C 8C 98 OA 20 CE 30 AD C9 DO 4C
20 3C 3C A5 D4 F6 39 Fl 59 EC
OF OF OE OF 14
AE 36 OF 2A 07 03 BC 14 08 36 OF 37 OF EE 34 OD 00 9B 03 47
14 OF CO 13
1452: 4C 67 13 1455 : BD 88 CO 1458: 60
1459: AO 20 145B: 88 145C: FO 5C 145E 1461 1463 1465
BD 10 C9 00
8C CO FB D5 F4
1010 1011 1012 10 13 10 14 1015 1016 1017 10 18 10 19 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
Zurück zu Sektor 0, damit die Sektore n benachbarter Tracks in der richtigen Anordnung nebeneinander li ege n
SEEKO
LDA STA DEC BEQ JSR BCS LDA BNE J SR BCS
U20 RDVER RDV ER NOTFOUND RDADR16 SEEKO RSEC SEEKO VREAD16 SEEKO
;nicht Sektor 0 ;Daten l esen
Verify erfolgreich, a l so anzeigen LDA LDY STA BNE JSR LDX I NY STY STY TYA ASL J SR DEC BMI LDA CMP BNE JMP
UAE TRACKC ZEI LE14,Y ONTRKO SYNCZAHL SLOT2
GOWRNXT
JMP
WRNEXT
ALLWRT
LDA RTS
MOTOROFF,X ;Motor aus
ONTRKO
I,,·
; ausgeben ;Track 07 ;Synczahl verr i ngern ;nächste Spur
TRACKC TRKPOS SEEKABS TRACK ALLWRT KEY U9B GOWRNXT ESCENDE
; *2
; <ESC> 7 ;Ne i n, weiter ;Abbruch
a l le Datenbytes lesen und Checksum bilden gelesenen Datenbytes werden verworfen VREAD 16 VDATA , VDT
VDTO
LDY DEY BEQ
U20
;Versuchszahl
VDERR
; Lesefeh l er
LDA BPL CMP BNE
DATASTRB,X ;Datenprol og lese n VOT ;warten UD5 VOATA ;noch ni cht
11.4 Das wirbelnde Byte: Byte-Blizzard
1467: 1468: 146B: 146D: 146F: 1471 : 1473: 1476: 1478: 147A:
EA BD 10 C9 DO AO BD 10 C9 DO
8C CO FB AA F2 56 8C CO FB AD E7
147C: 147E: 1480 : 1483 : 1485: 1488: 1489: 148B:
84 A9 BC 10 59 EA C6 DO
18 00 8C CO FB 00 OF
148D: 1490: 1492 : 1495: 1496: 1498:
BC 10 59 EA E6 DO
8C CO FB 00 OF
149A : 149D: 149F: 14A2:
14M: 14A5: 14A8 : 14AA : 14AC: 14AE: 14AF: 14B2 : 14B4: 14B6: 14B8 : 14B9:
BC 10 D9 DO
EA BD 10 C9 DO EA BD 10 C9 DO 18 60
14BA: 38
18 F3
18 F3
8C CO FB 00 OF 16
8C CO FB DE OC 8C CO FB AA 02
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
VDTI
VDT2
NOP LDA BPL CMP BNE LDY LDA BPL CMP BNE
259 DATASTRB,X VDTI UAA VDTO U56 DATASTRB,X VDT2 UAD VDTO
Pause l esen warten ; muß kommen ;Datenbytes ; le se n ; warten ;muß kommen
Datenfeld l esen für Checksum-Prüfung Dat en werden ni ch t gespeichert
VDATI
VDAT2
STY LDA LDY BPL EOR NOP DEC BNE
INDEX UOO DATASTRB,X VDATI LUET-$96 ,Y
LDY BPL EOR NOP INC BNE
DATASTRB , X VDAT2 LUET- $96,Y
INDEX VDATI
INDEX VDAT2
Jetzt Checksum VDAT3
LDY BPL CMP BNE
DATASTRB , X VDAT3 LUET- $96,Y VDERR
Datenfeld-Epi l og prüfen
VDAT5
NOP LDA BPL CMP BNE NO P LDA BPL CMP BNE CLC RTS
VDERR
SEC
VDAT4
DATASTRB , X VDAT4 UDE VDERR DATASTRB,X VDAT5 UAA VDERR
260
11. Schnell wie der Wind
14BB: 60
14BC: 14BE: 14CO: 14C2 : 14C4 : 14C6: 14C8:
14C9: 14CA: 14CC: 14CF:
A9 C5 A5 E9 85 C9 60
00 IF IF 01 IF 06
4A 90 04 BO 8A CO 60
1400: BO 8B CO 1403: 60
1404: 1406: 1409: 140B: 140E:
140F: 14E2: 14E5: 14E8: 14EA: 14EC:
14EE : 14FO: 14F2: 14F4: 14F6: 14F8: 14FA: 14FC: 14F'D: 14FE: 1501: 1502:
A6 BO A6 BO 60
BO BO BO A9 85 A9
86 85 C5 FO A9 85 AO 18 98 20 88 10
06 88 CO 08 88 CO
8E CO 8C CO 89 CO 50 EB 00
17 EC EB 59 00 CE 03 44 15 F9
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
RTS Zahl der Sync-Bytes verringern SYNCZAHL LOA CMP LOA SBC STA CMP RTS
UO O SYNCS SYNCS UOl SYNCS U06
;noch 14+4 Syncs? ; akt. Anzah l ;-2 bei CC, -1 bei CS ; abspe ichern ; noch 10 (6+4) ? ;CS = OK, CC = Fehler
gewünschtes Laufwerk anwählen ORVWAHL
LSR BCC LOA RTS
; gerade/ungerade? ORV2 ;gerade - ) Drive 2 ORVIENAB,X ;Orive 1 an
ORV2
LOA RTS
ORV2ENAB ,X ;Orive 2 an
Motor für Orig. und Kopie aus MOTOFF
LOX LOA LOX LOA RTS
SLOTI MOTOROFF,X SLOT2 MOTOROFF , X
Auf Spur 0 positionieren . TRKOPOS
LOA LOA LOA LOA STA LOA
INPUTMOO ,X OATASTRB,X ;Schleuse normalisieren MOTORON,X U50 ;Spurist * 2 auf 80 (40) SPURIST UOO ; Spursol l * 2 auf 00
positioniert auf die gewünschte Spur SEEKABS
PHASOUT
STX STA CMP BEQ LOA STA LOY CLC TYA JSR OEY BPL
TEMP SPURSOLL SPURIST SPUROA UOO PTR U03 ARMMOVI PHASOUT
; Sloh16 ;gleich, Prozedur erfüllt ; Oelay-Index auf Maximum ;Ourchlaufzähler ;alle Ph asen aus
11.4 Das wirbelnde Byte: Byte-Blizzard
1504: 1506: 1508: 1509: 150B : 1500 :
A5 85 38 E5 FO BO
EB CF EC 31 06
150F: 49 FF 1511 : E6 EB 1513: 90 04
1515 : 1517 : 1519: 151B: 1510: 151F: 1521: 1523: 1524: 1525: 1528: 152B: 152E: 1530: 1531: 1534: 1537: 153A: 153C :
69 C6 C5 90 A5 C9 BO A8 38 20 B9 20 A5 18 20 B9 20 E6 00
FE EB CE 02 CE 08 01 42 15 50 15 60 15 CF 44 15 58 15 60 15 CE C6
153E: 20 60 15 1541 : 18
1542: 1544: 1546: 1547: 1549: 154A: 1540 : 154F :
1550 : 1553 1558 155B
A5 29 2A 05 AA BD A6 60
01 24 70 22
EB 03 17 80 CO 17
30 20 2C IF'
28 lE 26 lE
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 11 98 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 10 lC 1224 10 lC 1225
POSIT
LDA STA SEC SBC BEQ BCS
261
SPURIST PTR+l
;Track jetzt *2 ;retten
SPURSOLL ISTDA AUSSEN
;- gewünschte Spur ;gleich, also Ende ;> Arm zu we it innen
nach innen bewegen EOR INC BCC
UFF SPURIST DELAYNDX
;Vorze ich enwechsel, -1 ;akt. Spur erhöht ; immer
nach außen bewegen AUSSEN
ADC DEC DELAYNDX CMP BCC LDA DIFFKLN CMP BCS TAY DELMAX SEC JSR LDA JSR LDA CLC J SR LDA JSR INC BNE
;nach auße n . -1, akt . Spur +1 ;Vergl Diff-l / De lay ; Di fferenz kleiner ; Del ay-Index kl einer ; ( $08 (Maximalwert) ;Nein, Y unverändert ;Akku neuer Del ay-Index ; Ph ase an zum Track ARMMOVER ;Arm bewegen PHONDEL ,Y ; Phase ON De l ay MSWAIT ;warten PTR+l ;alt e Spurnummer ;di ese Phase aus ARMMOVI ;aussc halten PHOFFDEL,Y ; Phase OFF Del ay MSWAIT ;warten PTR ; Du rc hlaufzähler +l POSIT ; imme r , neuer Du rchgang
ISTDA
MSWAIT
JSR CLC
UFE SPURIST PTR DIFFKLN PTR U08 DELMAX
;noch warten ;dann diese Phase aus
Phasen-Adre ss ie ru ng. ARMMOVER LDA ARMMOVl AND ROL ORA TAX LDA LDX SPURDA RTS
SPURIST U03
; Ein sprung "Track jetzt" ; Phasennr. ausblenden ; C=l ON, C=O OFF TEMP ;S l ot*16 einblenden ; Index Phase nanst euerung PHASEOOF ,X ; Phase sch a lt en TEMP ;S l oh16 zurück
Verzögerungs tabelle n für Armbewegungen PHONDEL
HEX
01302824201EIDIC ; Verzögerun g Ein
PHOFFDEL HEX
702C2622 1FIEIDIC ;Verzögerung Au s
262
1560: 1562: 1563: 1565: 1566: 1568: 156A:
156B: 1560: 156F : 1570 : 157 1 : 1573 : 1575: 1576: 1578: 157A: 157B: 1570:
157E : 1581 : 1583: 1585: 1588: 158A: 158B: 1580: 158E: 1590 : 1592: 1594: 1596 : 1598: 159A: 159B : 1590: 15AO: 15Al: 15A3: 15A5: 15A6 : 15A8: 15A9:
11. Schnell wie der Wind
A2 CA 00 38 E9 00 60
AO A9 38 48 E9 00 68 E9 00 88 00 60
20 A9 AO 20 84 68 85 68 85 AO E6 00 E6 BI 48 09 20 68 30 A5 48 A5 48 60
12 FO 01 F6
05 FF 01 FC 01 F6 FO
80 FE 15 02 5B FB 24 CE CF 00 CE 02 CF CE 80 FO FO EF CF CE
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 127 1 1272 1273 1274 1275 1276 1277 1278 1279
Pause f ür Kopfbewegungen , MSWAIT LOX 41$12 ;kleine Schleife MSWI OEX BNE MSWI SEC SBC 41$0 1 ;große Sc hl e ife BNE MSWAIT RTS Pause für Motoranlauf PAUSE PAUSEI PAUSE2 PAUSE3
LOY LOA SEC PHA SBC BNE PLA SBC BNE OEY BNE RTS
41$05 U FF
;ca. 0,83 sec
41$0 1 PAUSE3
;wie Monitor
41$01 PAUSE2 PAUS EI
Oruckroutine, mehrere Ei nsprünge PRINT PRINTl PRINT2 PRINT3 PRINT4
PRI PR2
JSR LOA LOY JSR STY PLA STA PLA STA LOY I NC BNE INC LOA PHA ORA JSR PLA BMI LOA PHA LOA PHA RTS
SETI NV 41$15 41$02 TAB V CH PTR PTR+l 41$00 PTR PR2 PTR+l (PTR) , Y 41$80 COUTI
;Bit 7 se tzen ;ausgeben
PRI PTR+l
;Pos iti v Endeke nnun g ;Rücksprungadresse ;auf den Stack ;schieben und mit
PTR
;RTS anspringen
Origin a l- und Copyanzeige löschen
263
11.4 Das wirbelnde Byte: Byte-Blizzard
15AA : 20 B2 15 15AO: 00 16
15AF: 15B2 : 15B4: 15B7: 15BA : 15BF :
15C2 : 15C5: 15C7 : 15C9 : 15CC : 15CF : 1501 :
1504: 1507 : 150A : 1500 : 15E5: 15EO: 15F5: 15F8: 15FB: 15FD : 1600: 1608: 1610: 1613: 1616:
1619: 161C: 1610: 161E: 162 1 : 1624: 1627 : 162A: 1632: 1635:
20 A9 20 CF C7 4C
20 A9 AO 20 CB C9 4C
20 20 00 C7 CE BI C5 87 80 BE Cl C3 04 20 4C
BO 68 68 80 20 20 03 02 04 4C
80 04 83 02 C9 84
80 07 05 85 CF 45 84
58 8A 02 02 CF B6 AO 87 80 BE 03 CB BC OC 13
88 82 C2 7E C3 C5 DA 65
FE 15 C9 CE FE
FE 15 00 FE
FC 15 CF Cl C5 CB Al 87
1280 1281 1282 1283 1284 1285 1286 1287 1288 Cl 4C 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 CO CD 04 C9 AO CB
NORMAL
ORIGNORM COPYNORM
;immer
Original einlegen ORIGINV JSR ORIGNORM LOA JSR OCI JMP
SETINV t$04 PRINTI "ORIGINAL" SETNORM
Copy einlegen COPYINV JSR COPYNORM LOA LOY JSR OCI
SETINV t$07 t$05 PRINT2 "KOPIE"
JMP
SETNORM
Fehlermeldungen Programm benötigt 64K LCERROR
JSR JSR ASC
HOME PRINT4 "PROGRAMM BENOETIGT 16K-KARTE
HEX
8787878080
OCI
"» TASTENDRUCK BOOTET <<"
JSR JMP
ROKEY REBOOT
AO C2 C5 C7 04 AO Cl 02 04
1307
04 1308 04 C5 CE AO C2 CF 3C FO 1309 12 1310 1311 1312 1313 CO 1314 1315 1316 CO 1317 15 1318 15 1319 C8 1320 C9 C2 03 20 16 1321 1322
JSR BNE
C4 02 05 CF 04 C5
Oisk schreibgeschützt WPROT
LOA PLA PLA STA JSR JSR OCI
MOTOROFF,X ;Motor aus
JMP
ERROR
ROM COPYINV PRINT "SCHREIBSCHUTZ-"
C3 C8 05
I "
264
11 . Schnell wie der Wind
1638: 163B: 163E: 1641 : 1649: 164C:
20 20 C6 CD C7 4C
C2 7E CF Cl D3 65
15 15 D2 D4 2D 16
164F: 1652: 1655: 1659:
20 Cl C5 4C
7E C4 D3 65
15 D2 D3 16
165C: 20 7E 15 165F: C4 Cl D4 1662: C5 CE 2D
1665: 1666: 1667: 166A: 166C: 166F: 1672: 1673 : 1676 : 1679: 167C:
68 68 AE A9 9D 20 87 C6 CC 20 20
167F: 1682: 1684: 1687 : 168A: 1692: 169A: 16AO: 16A3 : 16A6: 16A9: 16AC:
20 A9 20 C2 D4 D4 D5 20 2C 20 20 4C
37 OF AA 2A 07 8A 15 C5 C5 84 9C
C8 52 FE FC
D4 17 83 C9 C5 Cl C5 9C 10 OC AA C4
14
16AF : A9 00
15 D4 AO D3 C3 FC CO FD 15 10
Formatierung nicht möglich 1323 1324 1325 FORMFEHL JSR COPYINV 1326 JSR PRINT 1327 DCI 11 FORMATIERUNGS-" C9 C5 D2 D5 CE 1328 JMP ERROR 1329 1330 Adressfeld-Fehler 1331 1332 ADRFEHL J SR PRINT 1333 DCI "ADRESS- " 2D 1334 JMP ERROR 1335 1336 Datenfeld fehlerhaft 1337 , 1338 DATFEHL JSR PRINT 1339 DCI "DATEN-li 1340 1341 Fehlerposition ausgeben 1342 1343 ERROR PLA 1344 PLA 1345 LDX TRKPOS 1346 LDA *"*11 :Fehler 1347 STA ZEILE14,X 1348 JSR PRINT4 1349 HEX 87 ;Be11 1350 DCI "FEHLER" 1351 JSR SETNORM 1352 JSR CLREOL 1353 1354 Abbruch, aber Slot und Driv e merken 1355 1356 JSR MOTOFF ; Zeile 16 1357 LDA #$ 17 1358 JSR PRINT1 DCI "BITTE EINE TASTE DRUECKEN" 1359 C5 C9 CE C5 AO D4 C5 AO C4 D2 CB C5 4E 1360 JSR CLREOL BIT STROBE 1361 1362 JSR RDKEY 1363 JSR NORMAL 1364 JMP WRMSTRTI 1365 1366 Slot und Drive festlegen 1367 ; initi a li sieren 1368 SLOTDRI LDA #$00
265
11.4 Das wirbe ln de Byte: Byte-Blizzard
16Bl : 16B3: 16B5: 16B7: 16BA: 16BD: 16C5: 16C6: 16C8: 16CB: 16CC: 16CD: 16CE: 16CF : 16Dl: 16D3 : 16D5: 16D7 : 16D9 : 16DB: 16DE: 16El : 16E7 : 16E9 : 16EC: 16EE :
16EF: 16FO: 16Fl : 16F2: 16F3:
16F6: 16F9: 16FB: 16FE: 1700: 1702: 1704: 1706: 1708: 170A : 170C: 170E:
85 85 85 20 AO C5 3A AO 20 OA OA OA OA C5 85 DO A5 85 AO 20 CC C6 AO 20 85 60
08 1369 07 1370 17 1371 8A 15 1372 SLOTDR2 D3 D4 1373 C3 CB DO CC Cl D4 DA
STA STA STA JSR DCI
SLOT2 DRIVEl TEMP PRINT4 " STECKPLATZ :"
B8 F6 16
LDY JSR ASL ASL ASL ASL CMP STA BNE LDA STA LDY JSR DCI
U B8 ANSWER
08 08 04 07 17 OD 88 Cl D7 B3 F6 09
15 D5 C5 16
68 68 68 68 4C 50 10
2C 84 20 C9 FO C9 90 C5 BO 29 C5 DO
10 CO CE OC FD 9B ED Bl OA CE 06 OF 17 05
1710: 20 DD FB 1713: FO E6
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 D2 CB 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 141 6 1417 1418 1419
DRIVE
; ,,8" Obergrenze ,..,
16
SLOT2 ;am selben Controller SLOT2 ;nur mit 2 Drives DRIVE ;an verschiedenen Contr. DRIVEl TEMP ;HTAB UOD PRINT3 "LAUFWERK:"
3A LDY JSR STA RTS
UB3 ANSWER DRIVE2
;,,3 11
Obergrenze
Abbruch durch <ESC> ABBRUCH
PLA PLA PLA PLA JMP
;2* JSR vom Stack
WRMSTART
Antwort von der Tast atu r Obergrenze ( <) im Y-Regi s ter ANSWER TASTE
FEHL
BIT STY J SR CMP BEQ CMP BLT CMP BGE AND CMP BNE
STROB E PTR RDKEY U9B ABBRUCH UBl FEHL PTR FEHL U OF TEMP OK
;Tastatur vorbereiten ;Obergrenze merken ;Tastendruck ; <ESC >? ;Ja
JSR BEQ
BELL TASTE
;Piep ;neuer Versuch
;11 111
;zu klein ;Obergrenze ;zu groß ;%00001111 ; 1 Controller: 2 Drives
266
1715: 1716: 1718: 171B: 171E: 171F:
11. Schnell wie der Wind
48 09 BO 20 FO FD 20 8E FD 68 60
1720: 1722: 1723: 1725: 1727: 1729: 172B: 172E: 1730: 1733: 1735: 1737: 1739: 173B: 173D: 173F: 1740: 1741 :
A5 18 69 85 A2 AO BD 85 BD FO 85 B1 29 05 91 E8 E8 DO
1743: 1745: 1746: 1748 : 174A: 174C : 174F: 1751: 1754 : 1756: 1758: 175A: 175C: 175E: 1760: 1761 : 1762:
A5 18 69 85 A2 BD 85 BD FO 85 B1 29 05 91 E8 E8 DO
1764: 60
06 80 17 00 01 65 17 CE 66 17 OE CF CE OF 17 CE E8 08 80 17 00 79 17 CE 7A 17 OE CF CE OF 17 CE E8
1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473
Tastendruck ausgeben OK
PHA ORA JSR JSR PLA RTS
U BO COUT1 CROUT
;retten ; - ) ASCII ; ausgeben ; <e r>
;zurück ;das war's
Code-Modifikation für Slot SLOTMODI LDA CLC ADC STA LDX LDY OSLOTM LDA STA LDA BEQ STA LDA AND ORA STA INX INX BNE
SLOT1
CSLOTMOD LDA CLC ADC STA LDX CSLOTM LDA STA LDA BEQ STA LDA AND ORA STA INX INX BNE
SLOT2
MODEND
#$80 TEMP #$00 #$01 OSLMO,X PTR OSLMO+1,X CSLOTMOD PTR+1 (PTR), Y #$OF TEMP (PTR), Y
; Or i gina 1
OSLOTM
#$80 TEMP #$00 CSLMO ,X PTR CSLMO+1,X MODEND PTR+1 (PTR) , Y HO F TEMP (PTR), Y
;Copy
CSLOTM
RTS
Tabelle der zu modif. Adr esse n
11.4 Das wirbe lnde Byte: Byte-Blizzard
1765: 1767 : 1769 : 176B: 176D : 176F' : 1771: 1773 : 1775 : 1777:
38 47 5B 6F' 83 96 A8 B7 C7 00
OE OE OE OE OE OE OE OE OE 00
1779: 177B: 177D: 177F' : 1781 : 1783: 1785: 1787: 1789 : 178B: 178D: 178F' : 179 1 : 1793: 1795: 1797: 1799: 179B : 179D: 179F': 17Al : 17A3 : 17A5: 17A7 : 17A9 : 17AB: 17AD: 17AF': 17Bl : 17B3: 17B5: 17B7: 17B9 :
22 25 32 35 4F' 52 67 6A 85 88 91 94 C8 CB F'O F'3 ID 20 35 38 4D 50 64 67 82 85 B6 B9 C2 C5 DD EO 00
OC OC OC OC OC OC OC OC OC OC OC OC OC OC OC OC OD OD OD OD OD OD OD OD OD OD OD OD OD OD OD OD 00
17BB 17BD 17BE 17CO 17C l
A2 00 8A 29 CO 4A 4A
1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 150 1 1502 1503 1504 1505 1506 1507 1508 1509 15 10 1511 1512 1513 15 14 15 15 15 16 1517 15 18 15 19 1520 1521 1522 1523 1524 1525 1526 1527
267
OSLMO
ADR ADR ADR ADR ADR ADR ADR ADR ADR HEX
RDNIBBL RDNIBBLI RDNIBBL2 RDNIBBL3 RDNIBBL4 RDNIBBL5 RDN I BBL6 RDDAEPIL RDDAEPll 0000
CSLMO
ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR ADR HEX
WRS I WRS2 WRS3 WRS4 WRS5 WRS6 WRS7 WRS8 WRS9 WRSI0 WRS11 WRS12 WRS13 WRS14 GAP2 WRS15 WRS16 WRS17 WRS 18 WRS19 WRS20 WRS21 WRS22 WRS23 WRS24 WRS25 WRS26 WRS27 WRS28 WRS29 WRS30 WRS31 0000
Tabellen anlegen Sc hr e ibübe rse tzun gst ab . 4-mal kopie r en MAK ETABS LDX TABLOOP TXA AND LSR LSR
n oo n co
;800- 83F' ;840-87F' ;880-8BF' ; 8CO-8F'F'
00 10 20 30
268
11. Schnell wie der Wind
17C2: 17C5: 17C6: 17C7: 17CA: 17CB: 17CC: 17CF: 1700:
90 4A 4A 90 4A 4A 90 E8 00
00 08
1702 : 1704: 1707: 170A: 1700: 17EO: 17E3: 17E4 : 17E5: 17E6: 17E7: 17E9: 17EC: 17EO: 17EE: 17EF: 17FO: 17F2: 17F5: 17F6: 17F7 : 17F8 : 17FB: 17FC: 17FE:
A2 BO 90 90 90 90 8A OA OA 48 29 90 68 OA OA 48 29 90 68 OA OA 90 CA 10 60
3F 56 00 40 80 CO
17FF 1802 180A
00 09 00 OA EB OF OB OB OB OB
CO 00 03
CO 40 03
80 03 06
EO 00 BO AO 90 80 20
STA 1528 LSR 1529 LSR 1530 STA 1531 LSR 1532 LSR 1533 1534 STA 1535 INX BNE 1536 1537 LOX 1538 1539 LOOP2 LOA 1540 STA 1541 STA 1542 STA 1543 STA 1544 TXA 1545 ASL 1546 ASL 1547 PHA 1548 ANO 1549 STA 1550 PLA 1551 ASL 1552 ASL 1553 PHA 1554 ANO 1555 STA 1556 PLA 1557 ASL 1558 ASL 1559 STA 1560 OEX 1561 BPL 1562 RTS 1563 1564 Hi-Byte vom 1565 1566 1567 PUFTAB HEX 70 60 50 40 30 1568
WRTRANS1,X ;900-93F :00 ;940-97F:04 ;980-9BF:08 WRTRANS2,X ;9CO-9FF:OC ;AOO-A3F:00 ;A40-A7F :01 WRTRANS3,X ;A80-ABF:02 ;ACO-AFF:03 TABLOOP n 3F SUET,X WRTRANS4,X ;BOO-B3F WRTRANS4+$40,X ;B40-B7F WRTRANS4+$80,X ; B80-BBF WRTRANS4+$CO,X ;BCO-BFF
;300-30F:00 ;3 10-31F:40 nco ROTRANS1,X ;320-32F:80 ;330-33F:CO ;340-343:00 ;344-347:40 ;348-34B :80 ; 34C-34F : CO n co ROTRANS2,X ;37C-37F : CO ;380:00 ;38 1 :40 ROTRANS3,X ;382:80 ;383:CO LOOP2 ;3BF:CO Speicher für jeden Track EOOOBOA09080706050403020
269
Anhangl 6502/ 65C02-Tabelle Funclion
load
Mnemon .
Immedi. Zero-Po Zero , X Zero, Y Absol. Abs. X Abs, Y lind_ XI (Ind). Y Implizit Relaliv ( Ind ) Op Cy Op Cy Op Cy Op Cy Op Cy Op Cy Op Cy Op Cy Op Cy Op Cy Op Cy Op Cy Op Cy Akku
LOA LOX LOY
Store
A9 A2 AO
STA STX STY
AS A6
B5
4
B4
4
3 3
95
4
3
94
4
A4
3 3 3
85 86 84
B6
AO 4 AE AC
96
4
80 8E 8C
BO 4- B9 4' Al BE 4' BC 4-
6
Bl
5'
B2
S
90
6
91
6
92
S
5
99
5
81
Transfer
TAX TXA TAY TYA
AA 8A A8 98
Stack Ptr
TSX TXS
BA 9A
Stack
PHA PLA
48
PHP PLP CLC SEC CU SE I CLO SEO CLV
18 38 58 78 08 F8 B8
Status
R.
Flags
Jump
JMP JSR
Return
RTS RTI
Compare
CMP CPX CPY BIT
Branch
BMI BPL BEO BNE BCS BCC BVS BVC
N =O ZoO C =O V=O
C5 E4 C4 24
05
4
34
4
004'
CO EC CC 2C
3C
09 4' Cl
6
- Z - Z - Z -
NN N N-
-
Z Z Z Z
-
N -
- Z -
68
N -
- Z -
08 28
3 4
NVOIZC - - - 0 1 - - 0
- 0 - 1 0 1 -
6e 5/6 60 40
C9 EO CO 89
NN N-
3 4
7e 6-
4C 20
Sta tus
NVO I ZC
NVOIZC
01 5-
02
•
5
N N N 76
-
-ZC -ZC -ZC - Z -
30 2+
10 2..FO 2+
00 Ba 90 70 50
2 "" 2+ 2+ 2+ 2+
INC INX INY
IA
Decrement
OEC OEX OEY
3A
Add ISub!.
AOC SBC
69 E9
Boolean
A NO ORA EOR
29 09 49
SMt
ASL LSR
OA 4A
06 46
16 56
OE 4E
lE 716 SE 716
N -
o-
-Z C - ZC
ROlate
ROL ROR
2A 6A
26 66
36 76
2E 6E
3E 716 7E 7/6
N N -
- ZC - Z C
Sons tiges
NOP BRK
65C02
BRA
Increment
2
E6
2
5
F6
TSB
6
FE 716
6
CE 6 OE 7/6
65 ES
75 F5
4 4
60 EO
4 7D 4' 79 4' 4 FD 4- F9 4-
25 05 45
35 15 55
4
20 00 40
4 30 4' 4 10 4' 4 50 4-
5
61 El
39 4' 21 19 4- 01 59 4- 41
NNN-
- Z -
E8 C8 CA 88
N N N-
- Z - Z - Z -
NV- - Z C NV - - z C
31 11 51
32 12 52
N - - - z N - - - Z N - - - Z -
5' 5' 5'
2 7
- 1
80 3-
64 14 o.
74
•
DA 5A FA 7A ge le oe
9E
1 Takt mehr bei Sei lenübergang .
JMP (S HHLL) und JMP (SHHLL, Xl je 3 Bytcs: passen nicht in Systema tik kursiv = 65C02-Anderungen
NN-
- Z -
- Z -
5
,' = 2 T ak le bei N icht-Verzweigung, 3 Takte bei Verzweigung. 4 Takle bei Verzweigung mi t Sei lenübergang .
=
- Z -
72 F2
BYleanzaht
.=
- Z -
71 5' Fl 5'
EA 00
PHX PHY PLX PLY
TR8
EE
06
C6
S TZ
6
76 - - Z 76 - - Z -
270
A nhang2
Anhang 2: ASCII-Tabelle NUL @ § A B C EOT D E F BE LL G H TAB I K I FF RTN M 50 N 51 0 P XON 0 R 5 XOF F T U V W X Y Z E5C [A
00 01 02 03 04 05 06 07 08 09 OA OB OC OD OE OF 10 11 12 13 14 15 16 17 18 19 1A lB \ Ö lC
IÜ
10
lE _ lF 20 21 22 "" 23 S 24 % 25 & 26 27 28 29 2A + 2B 2C - 2D 2E 2F 30 31 32 33 4 34 5 35 6 36 37 38 39 3A 3B < 3C 3D > 3E ? 3F
()()()()()()()( 00000001 00000010 00000011 00000100 00000101 00000110 0000011 1 00001000 00001001 00001010 00001011 00001100 000011 01 000011 10 0000111 1 00010000 00010001 00010010 00010011 00010100 00010101 00010110 00010111 00011000 00011001 00011010 00011 011 000111 00 000 11101 00011110 00011111 00100000 00100001 00100010 00100011 00100100 00100101 00100110 00100111 00101000 00101001 00101010 00101011 001011 00 00101101 00101110 00101 11 1 00110000 00110001 001 10010 00110011 00110100 00110101 001 10110 00110111 00111000 001 11 001 00111010 0011101 1 001111 00 00111101 00111110 0011111 1
000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063
@§ A B C D E F G H
K L M N
o P Q
R 5 T U V W X Y Z [A \ Ö
I
Ü
_
a b
c d
e f
9 h
m n
o q r
u v x
z
lä
Iö
IÜ - ß DEL
40 01000000 064 41 01000001 065 42 01000010 066 43 01000011 067 44 01000100 068 45 01000101 069 46 01000110 070 47 01000111 071 48 01001000 072 49 01001001 073 4A 01001010 074 4B 01001011 075 4C 01001 100 076 4D 010011 01 077 4 E 01001110 078 4 F 01001 11 1 079 50 0101 0000 080 51 01010001 061 52 01010010 062 53 01010011 083 54 01010100 084 55 01010101 085 56 01010110 086 57 0101011 1 087 58 01011000 088 59 01011001 089 5A 01011 010 080 5B 01011011 091 SC 01011100 092 5D 0101 11 01 093 SE 01011110 094 5F 01011111 095 60 01100000 096 61 01100001 097 62 01100010 098 63 01100011 099 64 01100100 100 65 01100101 101 66 01 100110 102 67 01100111 103 68 01101000 104 69 01101001 105 6A 01 101010 106 6B 011 01011 107 6C 011 011 00 108 6D 01101101 109 6E 01101110 110 6F 01101111 111 70 01 110000 11 2 71 01110001 113 72 01110010 11 4 73 0111001 1 115 74 01110100 116 75 01110101 117 76 01110110 118 77 01110111 119 78 01111000 120 79 01111001 121 7A 011 11010 122 7BOll11011123 ic 011111 00 124 7D 0111 11 01 125 7E 01 111110 126 7F 01111111 127
@§ A B C D F G H
K L M N
o P Q
R 5 T U V W X Y Z [A \ Ö ) Ü
_
"" S % &
+
-
< > ?
60 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F AO Al A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF BO BI B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
10000000 10000001 10000010 10000011 10000100 10000101 10000110 10000111 10001000 10001001 10001010 10001011 10001 100 10001101 10001110 10001 111 10010000 10010001 10010010 10010011 10010100 10010101 100101 10 10010111 10011000 10011001 10011010 10011011 10011100 100111 01 1001111 0 10011111 10100000 10100001 10100010 10100011 10100100 10100101 10100110 10100111 10101000 10101001 10101010 10101011 101011 00 10101 101 10101110 101 01111 10110000 10110001 10110010 101 10011 10110100 10110101 1011011 0 101101 11 10111000 101 11001 101 11010 10111011 101111 00 101111 01 10111 110 10111111
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
@§ A B C D E F G H I
co Cl C2 C3 C4 C5 C6 C7
es
C9 CA K CB CC M CD N CE o CF P DO Q Dl R D2 5 D3 T D4 U D5 V D6 W D7 X D8 Y D9 Z DA [ A DB \ Ö DC I Ü DD DE _ DF EO a EI b E2 c E3 d E4 e E5 f E6 9 E7 h E8 E9 EA EB EC m ED n EE o EF P FO q Fl F2 F3 F4 u F5 v f6 w F7 x F8 F9 z FA I ä FB I ö FC I ü FD - ß FE DE L FF
11 000000 11 000001 11 000010 11000011 11 000100 11 000101 11 00011 0 11 000111 11001000 11 001001 11 001010 11 001011 11 0011 00 11 001 101 11 0011 10 11 0011 11 1101 0000 11 010001 11010010 1101 0011 11 010100 11010101 11 0101 10 11 01 0111 11 011000 11 011001 11011010 11011011 11011100 11 01 11 01 11011110 110111 11 11100000 11100001 11100010 11100011 11100100 11100101 11 10011 0 11100111 11 101000 11101001 11101010 111 01011 11101100 11101101 11101110 111011 11 11110000 11110001 111 10010 1111 0011 11110100 1111 0101 1111 011 0 11110111 11111000 111 11001 11111 010 11 11 1011 111 11100 11 111101 11 111110 111 11111
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
Anhang3
271
Anhang 3: Bildschirmdarstellung 1. Zeichensatz
Zeichen
Darstell ung Nor
! " # $
% & ,
( )
*
+ , /
0 1 2 3 4 5 6 7 8 9
, < =
> ?
AO Al A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF BO BI B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
Zeichen
Fis
Inv
60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71
20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
72
73 74 75 76 77
78 79 7A 7B 7C 7D 7E 7F
@§
A B C D E F G H
I J K L M
N 0 P
Q R S T U V W X Y
Z [Ä /Ö
jÜ /\
-
Darstellung Nor
Fis
Inv
CO Cl C2 C3 . C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF DO D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54 55 56 57 58 59 5A SB SC 5D SE 5F
00 01 02 03 04 05 06 07 08 09 OA OB OC OD OE OF 10 11
12 13
14 15 16 17 18 19 lA 1B lC 1D
lE IF
272
Anhang3 Zeichen
@ A B C D E F G H I
J K L M N
0 P Q R
S T U V W X Y Z
[
\ J 1\ -
Darstell ung Crtl 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
Zeichen IIplus IIe/llc
! " # $ % &
,
( )
*'
+ , -
a b c d e f g h i
J k I m
n
/ 0 1 2 3 4 5 6 7 8 9
, <
0
p
q r s t u v w
x Y z {ä
lö
=
} Ü
>
-ß
?
rub
Darstellung No r EO EI E2 E3 E4 ES E6 E7 E8 E9 EA EB EC ED EE EF FO Fl F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
Der zweite Zeichensatz des IIc un d des en hanced He e nthält vo n $40-$5F Mauszeichen und von $60-$7F den inversen Klei nbuchstaben-Zeichensatz.
273
Stichwortverzeichnis
Stichwortverzeichnis alphabetisches Verzeichnis
4&4-Codierung 230 6&2-Codierung 230 80STOREOFF 30 80STOREON 29 80Z/Z 29 80Z/Z Curso r 30 &-BeFehl 139
Blase n-Sort. 146 Blockgrafik 37 BLTU2185 BSORT 147 BSSERR 148 Bubble-Sort. 146 Byte-B lizzard 229 , 236
AlUH 164 A2UH 165 A4UH 164 Abrufsch leife 229 ABS 116 Access 211 Adressfe ld 227 A LLOCA TE INTERR UPT 209 Aillpersa nd 139 AND 117 ARYTAB 122, 125 ASCII 9 ATN 116 Ausgabe-Vektor 87, 223 AUX-Memo ry 29 Aux-Typ 212 AYINT 119
CATALOG 206 CHAIN-Progralllill 168 CHKCLS 142 CHKCOM 141 CHKOPN 142 CHKSTR 186 CHRGET 139 CHRGOT 140 CLEOLZ 15 CLOSE 206, 219 CLREOP 16 CLRFNBUF 186 CLRSC237 CLRSCR 37 CLRTOP 37 CMPLPRMS 188 Code , selbstillodif. 94 Code , verschiebbarer 162 Codierverfahren 230 COLCOUNT 44 COlllmand-Handler 222 COMP 118, 154 CON INT 120 CONNECT 87,188 COPYA 236 COPYBP 188 COPYFN 187
BASCALC 11 , 11 BASrc.SYSTEM 222 Basisadresse 70 BASUH 11 Bildschi rillausgabe 9 Bi ldschi rillspeicher 10 Bitg rafik-Mod us 96 BitIlluster 44 BKGND 46
274 COPY IIE 236 COPY IIplus 236 COS 116 COUT 19 CREATE 211 Cross-Reference 160 CROUT 115 CSWLlH 86 Ctrl-D 86 Ctrl-G 24 Cursor-Steuerung 24 DATA 143 Datenfeld 227 Datenregister 229 DATPTR 188 DCT203 DEALLOCATE INTERRUPT 210 DELETE 206 Deskriptoren-Stack 136 DESTROY213 Dimension 126 Disk-Controli er 226, 232 Diskette 227 Diskettenzugriff 226 DIVlO 116 DOS 86 DOSERR 188 Double-HIRES 42 DOWN-SCROLL 13 DRAW 52 DRAW154 Druckroutine 95 DRWPARA53 Ein-/Ausgabe 86 Eingabe-Vektor 87, 223 EOF221 Epilog 227 EPSON-Interface 90 EXP 116 Exponent 107 FADD 117 FADDH 116 FADDT 117 FALSE 116 Farbbit 47 , 59
Stichwortve rzeichnis FCOMP 118 FDIV 117 FDIVT 117 Feld 122 Feldvariablen 125-126 Fenster 61 Fenster-Demo 61 File-Lese r 191 File-Manager 187-188, 203 File-Puffer 205 Filepuffer 223 FILEREAD 188 Filetyp 188 Fi le-Typ 205 , 212 FIN 120, 135 FLASH 10, 25 FLENGHT127 Fließkomma-Akkum ul ator 110 Fließkomma-Format 106 Fließkomma-Paket 106 Fließkomma-Zahlen 111 Flimmern 72 FLOAT120 Floating-Point 106 FLUSH 220 FM-Arbeitsbereich 204 FM-Feh lercod e 204 FM-Parameterliste 204 FMULT 112 , 117 FMULTI 112, 117 FNDLIN 183 Formatieru ng 227 Form, gepackte 108 Form , norm alisierte 107 Form , ungepack te 108 FORPNT 137 FOUT 120 FP-Operationen 116-118 FPWRT 117 FP-Zahlen- Vergl. 154 FREEB UFR 224 FRESTR 186 FRETOP 124 FRMEVL 156 FSUB 117 FSUBT 117 Funktion 122, 125
275
Stichwortverzeichnis Ganzzahl122 GAP 228 Garbage Collection 125 , ]83 GBASLIH 44 GDBUFS 135 ge pack te Form 108 Geschwindigke it 28 GETADR 120, ]57 GETARYPT 128 GETBUF ]87 GETBUF222 GETBUFR 224 GETEOF221 GET FILE INFO 215 GETFMPL202 GETTOB 202 GETLN 134 GETLNI135 GETLNZ 134 GET MARK 220 GETNUM 159 GET PREFIX 217 GET TTME 211 GIVAYF 119 GR35 Grafik , doppelthochaufl . 42 Grafik , hochaufl öse nd e 41 Grafik , ni edriga uflöse nd 32 Half-Tracks 233 Hauptspeicher 29 HCLR 46 HCOLOR 48 HCOLOR144 HCOLORZ44 Header 227 HEX 24 60 HEX 2C60 HEX-DEZ 155 HFIND 51 HGLIN 50 HGR45 HGR245 HGR372 HGR472 HGR anzeigen 45 HGR-Drucker 85 HIGHDS 127 , 185
HIGHTR 185 HIMEM186 HIRES 34 HIRES] 41 HTRES241 1-URES-Adressierung 42,70 HIRES-Farben 46 HTRES-Routinen 41 HIRES-Schrift 73 HTRES-Scroll 54 HIRES verschieben 54 HISCR 29,34 HLINE 36 HMASK 44 HNDX44 HOME 16 HPAG44 HPLOT 50 HPOS 51 Informationsblock 126 TNIT 13, 203 , 207 INSDS2165 INSTDSP 165 TNT 116 In terface 95 Interrupt-Routinen 209 INVERSE 10 TOB 202 IIO-Block 202 Joy 104 Kommentar 183 Konvertierungs-Rout. 119 Kopierprogramm 226 Kopierzeiten 236 KSWLlH 86 Lautsprecher 100 LENGTH 165 LINGET 183 LTNPRT 159 Loch-Dateien 221 LOCK 206 Locksm ith 229 , 236 LOG 116 Logische Operationen 117
276
Stichwortverzeichnis
LOMEM 122, 183 LORES 34 LORES- Adress ierung 33 LORES-Farbtabe lle 33 LORES-Grafik 32 LORES-Seiten 32 Löschprogramm 97-98 Löschro utin e 16 LOWSCR 29, 34 LOWTR 127, 185
Null (Zah l) 109 NUMDIM 127 NUMTYP 127 NXTAl 165 NXTBUF 187
Machine-Language-Interface 208 MAIN-Memory 29 Mantisse 107 Matrixd ruck er 85 Matrize n 125 MAXFILES 223 MFAC 110 MISMTCH 141 MIXCLR 34 MIXSET 34 MKINT 119 MLI-A ufruf 208 MONZ 164 MOVE 189 MOVEIF 119 MOVE2F 119 MOVEFM 119 MOVEFS 119 MOVEMF 119 MOVESF 119 MOVESM 118 MOVEZF 119 MOVFM 112 MULTlO 116 Multi pli kation mit 7 71 MUSIC 100 Musikprogramm 101
Page-Fl ipping 72 Parameterli ste 187 Parameterübergabe 139 PARMBLOCK 209 PCADJ3 165 PCLlH 165 Pi 111 PLOT 37 Polling Loop 229 POSITION 207 PRBYTE 115 Prenibble 23 1 PRINT 20 PRNTAX 157 PRNTFAC 120 PRNTYX 158 ProDOS 86, 208 PRODOS.SYSTEM 222 PROGRAMMERS AID 101 Prolog 227 PROMPT 134 Prüfsumme 228 PSHMFAC 120 PTRGET 127- 128 Pufferverwaltung 223 PULLSFAC 121
NEGOP 116 NEWLINE 217 NEWSTT 190 NEXTCOL40 NOBUFS 187 NORM 116 NORMAL 10 no rm alisierte Form 107 NOT 11 6- 117
ON UN E 216 OPEN 188 , 191, 205,217 OR 117 Overlay-Manager 168
Querverweis 160 QUINT 120 QUIT210 RD2BYTE 188 READ 203 , 206, 218 READ BLOCK 210 REBOOT21O Ree lle Za hl 122 relokativ 162
277
Stichwortverzeichnis RENAME 206, 213 RESTORE 92, 188 Ringtausch 138 RND 116 RNDB 116 R ückspru ngadresse 167 RWTB 192 RWTS 192 RWTS -Parameterliste 202 Saplin g 215 SAVE 92 SCALEZ44 Schnelkopierer 228 Schrift-G enerato r 75 Schriftm at ri x 74 Scratch-Bytes 43 Scratchpad 11 SCRN 40 SCROLL 13 Seedlin g 215 SEEK 203 Sektor 227 selbstmodif. Code 94 SET BUF221 SETCOL36 SET EOF221 SET FILE INFO 214 SETGR 35 SETHCOL 49 SETINV 25 SETKBD 187 SET MARK 220 SETNORM 25 SET PREFIX 216 SETIXT 12 SETVID 187 SFAC 110 SGN 116 SGNA 116 SGNFLT 120 Shape-Ad resse 53 SHAPELIH 44 SHAPEPNT44 Shapes 51 SIN 116 SNGFLT 137 Softswitches 33 , 232 Sortieralgori thm us 146
Sortierprogramm 146 SPEED 28 Speicherbelegung 123 Speicher reservieren 224 SQR 116 Stack 167 Startad resse 164 Steppermotor 233 STKINI1 89 Storage-Typ 215 STR$ 69 STRCMP 151, 153 STRCPY 137 STREND 125 Strin gpoo l 185 STRLITl136 STROUT27 Strukturblock 126 Subdirectory 215 SUBFLAG 127 Superq uick 229, 236 Super Serial Card 96 SWAP 138 Sync-Bytes 229 SYNCHR 143 Synchro nisa tio ns-Byte 227 Sy ncs 227 Sy nc-Signature 236-237 SYNTERR 158 Tabelleneintrag 124 Tabu lator horz . 22 Tab ul ato r vert. 22 TABV22 TAN 116 TEMPPT 136 TEXT-Adressierung 10 Textausgabe 29 Textbildschirm 9 Textfenster 12 Textfile 191 Textpointer 139 To nerzeugung 100 T rack 227 Track-Sek to r-Li ste 202 Trailer 227 Tree 215 Trick-Byte 60
278 TRUE 116 TSL 202 TXTCLR34 TXTPTR 127, 139 TXTSET34 TYPE 191 Übertragungs-Ro utinen 118 UFO 105 Uhrenroutine 211 ungepackte Form 108 UNLOCK206 UNLOCK-Trick 191 VALTYP 127 Variab le, einfache 122, 125 Variable , Felder 126 Variab len-Kopf 126 Va ri ab lenn ame 124, 133 Variab len suchen 127 Variablen tauschen 138 Variablen-Übergabe 129 VARL 119 VARL1119 VARNAM 127 VARPNT 127 VARTAB 122 Vergleich 94, 118 VERIFY207
Stichwortverzeichnis verschiebbarer Code 162 Verzöge ru ngsschl eife 16 Videx-Karte 29 VLINE 36 Vorzeichen-Byte 113 VTAB 15 VTABZ 15 VTOC206 WAIT 16 Werteblock 126 WNDBTM 12 WNDLFT 12 WNDTOP 12 WNDWDTH 12 WRITE 203 , 206, 219 WRITE BLOCK 211 XDRAW 52 XDRAW154 Zahlen basis 155 Zeichenkette 122 Zeichen ketten-Vergl. 151 Zeichensatz 10 ZEROFAC 116 ZEROPRMS 187 Z usatzspeicher 29
numerisches Verzeichnis $OOOF NUMDIM 128 $0011 V AL TYP 128 $0012 NUMTYP 128 $0014 SUBFLAG 128 $0016 CMPFLG 151 $OOIA SHAPEL 44 $OOlB SHAPEH 44 $OOIC HCOLOR1 44 $0020 WNDLFT 12 $0021 WNDWDTH 12 $0022 WNDTOP 12 $0023 WNDBTM 12 $0024 CH 22 $0025 CV 22
$0026 GBASL 44 $0027 GBASH 44 $0028 BASL 11 $0029 BASH 11 $002F LENGTH 165 $0030 HMASK 44 $0033 PROMPT 134 $0036 CSWL 86 $0037 CSWH 86 $0038 KSWL 86 $0039 KSWH 86 $003A PC 165 $003C Al 164 $003E A2 165
279
Stichwortverzeichnis $0042 A4164 $0044 NXTB UF 187 $0050 LINNUM 184 $0052 TEMPPT 136 $0064 FLENGTH 128 $0067 TXTI AB 123 $0069 VATI AB 122 $006B ARYTAB 123 $006D STREND 125 $006F FRETOP 124 $0073 HIMEM 123 $007D DATPTR 188 $0081 V ARNAM 128 $0083 V ARPNT 128 $0085 FORPNT 137 $0094 HIGHDS 128 $009B LOWTR 128 $009D MFAC 110 $OOAO VPNT 137 $00A5 SFAC 110 $OOAD STRNG2 137 $00B1 CHRGET 139 $00B7 CHRGOT 140 $00B8 TXTPTR 139 $00E4 HCOLORZ 44 $00E5 HNDX 44 $00E6 HPAG 44 $00E7 SCALEZ 44 $00E8 SHAPEPNT 44 $OOEA COLCOUNT 44 $OOFI SPEED 28 $03DC GETFMPL 202 $03E3 GETIOB 202 $03EA CONNECT 87 $A095 CLRFNBUF 186 $AIAE ZEROPRMS 187 $A471 FILEREAD 188 $A47A RD2BYTE 188 $A6D2 DOSERR 188 $A71A CMPLPRMS 188 $A 743 COPYFN 187 $A 74E COPYBP 188 $A764 GETBUF 187 $BEF5 GETBUFR 224 $BEF8 FREEBUFR 224 $BFOO MLI 208
$COOO 80STOREOFF 30 $C001 80STOREON 29 $COOC COL800FF 239 $COOD 80COL 42 $C050 TXTCLR 34 $C051 TXTSET 34 $C052 MIXCLR 34 $C053 MIX SET 34 $C054 LOWSCR 29 , 34 $C055 HISCR 29, 34 $C056 LORES 34 $C057 HIRES 34 $C05E DHIRESON 42 $C05F DHIRESOFF 42 $D39A BLTU2 185 $D539 GDBUFS 135 $D61A FNDLIN 184 $D683 STKINI 189 $D7D2 NEWSTI 190 $D849 RESTORE 189 $D995 DATA 143 $DAOC LINGET 184 $DA9A STRCPY 137 $DB3A STROUT 27 $DD6C CHKSTR 186 $DD76 MISMTCH 148 $DD7B FRMEVL 157 $DEI0 PSHMFAC 120 $DE47 PULLSFAC 121 $DE98 NOT 116, 117 $DEB8 CHKCLS 142 $DEBB CHKOPN 142 $DEBE CHKCOM 142 $DECO SYNCHR 143 $DEC9 SYNTERR 158 $DED5 VARL 119 $DEE9 VARL1119 $DF4F OR 117 $DF55 AND 117 $DF5D FALSE 116 $DF60 TRUE 116 $DF6A COMP 118, 154 $DF7D STRCMP 151, 153 $DFE3 PTRGET 128 $E108 MKJNT 119 $ElOC A YINT 119 $E196 BSSERR 148
280 $E2F2 GIVA YF 119 $E301 SGNFLT 120 $E3E9 STRLTl 137 $E5FD FRESTR 186 $E6FB CONTNT 120 $E752 GETADR 120, 157 $E7AO FADDH 116 $E7A7 FSUB 117 $E7BE FADD 117 $E7Cl FADDT 117 $E82E NORM 116 $E84E ZEROF AC 116 $E941 LOG 116 $E97F FMULT 117 $E982 FMULTT 117 $E9E3 MOVESM 118 $EA39 MULTlO 116 $EA55 DIVI0 116 $EA66 FDIV 117 $EA69 FDIVT 117 $EAF9 MOVEFM 119 $EBIE MOVE2F 119 $EB21 MOVEIF 119 $EB23 MOVEZF 119 $EB2B MOVEMF 119 $EB53 MOVEFS 119 $EB63 MOVESF 119 $EB72 RNDB 116 $EB82 SGNA 116 $EB90 SGN 116 $EB93 FLOAT 120 $EBAF ABS 116 $EBB2 FCOMP 118 $EBF2 QUINT 120 $EC23 INT 116 $EC4A FIN 120, 136 $ED24 LINPRT 159 $ED2E PRNTFAC 120 $ED34 FOUT 120 $EE8D SQR 116 $EE97 FPWRT 117 $EEDO NEGOP 116 $EF09 EXP 116 $EFAE RND 116 $EFEA COS 116 $EFF1 STN 116 $F03A T AN 116 $F09E ATN 116
Stichwortverzeichnis $F28C HIMEM1 86 $F390 GR 35 $F3D8 HGR2 45 $F3E2 HGR 45 $F3F2 HCLR 46 $F3F6 BKGND 46 $F411 HPOS 51 $F457 HP LOT 50 $F53A HGLIN 50 $F5CB HFIND 51 $F60l DRA W 52 $F605 DRA Wl 54 $F65D XDRA W 52 $F66l XDRA W1 54 $F6EC SETHCOL 49 $F7AA FSUBT 117 $F7D9 GETARYPT 129 $F800 PLOT 37 $F819 HLINE 36 $F828 VLINE 36 $F832 CLRSCR 37 $F836 CLRTOP 37 $F838 CLRSC2 37 $F85F NEXTCOL 40 $F864 SETCOL 36 $F871 SCRN 40 $F88C INSDS2 166 $F8DO TNSTDSP 166 $F940 PRNTYX 158 $F941 PRNTAX 158 $F956 PCADJ3 166 $FB2F TNIT 13 $FB39 SETTXT 12 $FB40 SETGR 35 $FB5B TABV 22 $FBCl BASCALC 11 $FC22 VT AB 15 $FC24 VT ABZ 15 $FC42 CLREOP 16 $FC58 HO ME 16 $FC70 SCROLL 13 $FC9E CLEOLZ 15 $FCA8 WATT 16 $FCBA NXTA1167 $FDOC RDKEY 201 $FDlB KEYIN 201 $FD67 GETLNZ 134
281
Stichwortverzeichnis $FD6A GETLN 134 $FD6F GETLN1 135 $FD8E CROUT 115 $FDDA PRBYTE 115 $FDED COUT 19 $FE2C MOVE 190 $FE80 SETINV 25 $FE84 SETNORM 25
$FE89 SETKBD 187 $FE93 SETVID 187 $FF3F RESTORE 92 $FF4A SA VE 92 $FF58 IORTS 167 $FF69 MONZ 164 $FFA7 GETNUM 159
Programm-Verzeichnis BASIC.SORT ]47 BYTE-BLIZZARD 238 BSORT.DEMO 150 BSORT 147 CHAR.SET 81 CLEAR197 CLEAR298 CROSSREFERENZ 160 CROSS2167 DOWN-SCROLL 13 DRWPARA 53 FARBTEST47 FILELESER 192 FP-DEMO 113 HEX-DEZ 155 HGR-DRUCKER 87 HGR-TEST91 HGR-WINDOW 63 HGR.W.DEMO-STARTER 62 HGR.WINDOW.DEMO 62 HIRES-SCROLL 54 HPRINTER 75 JOY 104 LORES 38 MUSIC.DEMO 103
MUSIC 101 OVL-DEMO 182 OVL-MANAGER 172 SORTER 183 PRINTER 183 PRINT DEMO 80Z/Z 30 PRINTl20 PRINTI 20 PRINT3 23 PRINT424 PRINT526 PRINT627 PRINTI28 SWAPl.DEMO 143 SWAP1140 SWAP2.DEMO 145 SWAP2144 TL.DEMO 19 TEXTLOESCH I 17 TEXTLOESCH2 17 TEXTLOESCH318 TEXTLOESCH419 UFO 105 V AR-DEMO 130 VARIABLEN-DEMO 129
HÜChia
Arne SChäpers
ProDOS-Analyse Versionen 1.0.1, 1.0.2, 1.1.1
1985, 470 S., kart., DM 68,ISBN 3-7785-1134-3
"Die ProDOS Analyse" ist die umfangreichste und detaillierteste Darstellung , die jemals ein Apple-Betriebssystem erfahren hat. Wer die "I nnereien" von ProDOS bis zum letzten Byte, z. T. bis ins letzte Bit kennen lernen möchte, braucht dieses Buch. Das komplette Betriebssystem (Urlader, MLI, Disk-Driver, RAM-Disk-Driver und UhrRoutine) mit Ausnahme des BASIC-SYSTEM wird mit umfangreichen Kommentaren und Übersichtstabellen disassembliert. Dabei werden alle bisherigen Versionen von 1.0.1 bis 1.1.1 berücksichtigt. "Die ProDOS Analyse" beschreibt erstmals auch mehrere Programmfehler, die bis in die neueste Version zu finden sind . Auch die nicht im "Technical Reference Manual" aufgeführten Eigenschaften von Pro DOS werden analysiert und
Dr. Alfred Hüthig Verlag Im Weiher 10 6900 Heidelberg 1
besch rieben, z. B. die vertrackten eingebauten Testroutinen zur Identifikation der verschiedenen Apple II Modelle und eventuel ler Nachbaugeräte. Progffimmieffi~dieProDOS
versionsabhängig "patch en" möchten, erhalten hier den genauen Überblick, wo was geändert werden muß , damit dies kei ne negativen Konsequenzen hat. Durch die minutiöse theoretische Sezierung von ProDOS eröffnen sich völlig neue programmierpraktische Perspektiven.
Ulrich Stiehl
Apple-Assembler
1984,200 S., 3 Abb., kart., DM 34,ISBN 3-7785-1047-9 Begleitdiskette DM 28,ISBN 3-7785-1048-7
"Apple Assembler" wendet sich an alle, die bereits Anfängerkenntnisse der 6502Programmierung haben z. B. aufgrund des Buches "Apple Maschinensprache" und nunmehr ein Nachsch lagewerk für ihren Apple II Plus l Ile / lic suchen, in dem alle wichtigen ROM -Routinen sowie eine Vielzahl sonstiger Hilfsprogramme in seiner systematischen Form zusammengestellt werden . Insgesamt umfaßt dieses Buch über 40 Util ities, darunter mehrere völlig neuartige Programme wie Double-Lores, Double Hilres, Screen-Format u.a. Der erste Teil enthält ein Repetorium der wichtigsten Befehle, Adressierungsarten und sonstigen Besonderheiten des 6502. Im zweiten Tei l werden alle Adressen des Monitors zusammengestellt, die für . Assembler-Programmierer von Nutzen sein können . Darüber
hinaus findet der Leser Unterroutinen für hexadezimale Addition ISubtraktion IMultiplikation I Division, Binär-HexASCII-Umwandlung usw. Der dritte Teil befaßt sich mit der Speicherverwaltung der Language Card und der Ile64K-Karte und enthält MoveProgramme zum Versch ieben von Daten in die und aus der Language Card sowie der 64KKarte. Der vierte Teil ist dem Applesoft-ROM gewidmet und listet eine große Anzahl nützlicher Interpreter-Adressen. Bei den Uti lity-Programmen liegt das Schwergewicht auf Fließkommamathematik einschließlich Print Using. Der letzte Teil behandelt den Text- und Graphikspeicher. Neben einem professionellen Maskengeneratorprogramm werden auch Routinen zur Double-Lores und DoubleHires-Grafik vorgestellt.
Dr. Alfred Hüthig Verlag Im Weiher 10 6900 Heidelberg 1
HÜChlia
Jürgen Kehrel
Apple-Assembler lernen Band 1: Einführung in die Assembler-Programmierung des 6502 165C02
1985,234 S., kart. , DM 38,ISBN 3-7785-1151-3 Begleitdiskette: DM 44,ISBN 3-7785-1243-9
Das zwei bändige Werk "Apple Assemb ler lernen" ist ein kompletter Kurs in der Assemblerprogrammierung des 6502 und des 65C02 auf dem Apple 11, der nicht da aufhört, wo andere Einführungen auf "weiterführende Literatur" verweisen. Starkes Gewicht wird auf die praktische Anwendung gelegt. Deshalb gehört zum Kurs ein vollwertiger 2-Pass Assembler, der als einer von wenigen die erweiterten Befehle der neuen IIc und lI e Prozessoren 65C02 verarbeitet und der auch lange Programme von mehr als 1 000 Zeilen in wenigen Sekunden übersetzt. Zu seinen professionellen Eigenschaften gehören neben 15 PseudoOpcodes, die die Arbeit mit Strings und Tabellen zu einem Kinderspiel werden lassen, ein Zei leneditor mit viel Komfort und die Fähigkeit, Quellcode in versch iedenen Formaten zu schreiben und zu lesen. Ein interaktiver Debugger und Simu-
lator hilft Ihnen, eigene und fremde Maschinenprogramme zu verstehen. Mit seinen vielfältigen und mächtigen Möglichkeiten läßt er.Sie hinter die Kulissen Ihres Rechners schauen. Sie können "sehen" , was abläuft, Ih re Vorstellungskraft wird angeregt und nicht nur einfach Ih r Gedächtnis strapaziert. Alle Programme sind 100 % kompakter Maschinencode, nicht einfach compiliertes Basic. Im ersten Band erlernen Sie inn erhalb von 35 Lektionen sämtliche Maschinenbefehle des Apple und die wichtigen Grundalgorithmen. Der Umgang mit dem Assembler und dem Simulator wird geübt, und zum Nachschlagen steht eine ausführliche Befeh lsbeschreibung mit vielen praktischen Beispielen bereit.
Dr. Alfred Hüthig Verlag Im Weiher 10 6900 Heidelberg 1
Hü-ehia
Heinrich Kersten
Apple-CP IM: AssemblerProgrammierung für Einsteiger, Fortgeschrittene und 6502-Kenner
1986, ca. 200 S., kart., ca. DM 38,ISBN 3-7785-1379-6 Begleitdiskette: DM 44,ISBN 3-7785-1380-X
Das Buch beschreibt die Assembler-Programmierung im Rahmen des CP IMBetriebssystems. Es wurde vorrangig für die Besitzer von Apple li-Geräten konzipiert. Der überwiegende Teil des Buches ist aber geräteunabhängig und somit auch für die Benutzer anderer CP IMtüchtiger Fabrikate (mit 8080 I Z80-Prozessor) von Interesse.
ge Basisprogramme (Konvertierungen , Binär- und BCDArithmetik) , umfassende Diskussionen der Debugger, Assembler und Linker sowie des CP I M-Betriebssystems (Speicherverwaltung , BDOS und BIOS-Aufrufe, Bildschirmfunktionen) . Den Abschluß bilden lauffähige Beispielprogramme und Utilities und ein umfangreicher Tabellen-Anhang.
Einsteiger erhalten im ersten Abschnitt einen Intensiv-Kurs (auch in der DDT-Anwendung) . Für Kenner der 6502Programmierung werden viele Querverweise vorgestellt. Der Z80-Befehlsvorrat wird im Detail erläutert. Es folgen wichti-
Dr. Alfred Hüthig Verlag Im Weiher 10 6900 Heidelberg 1
HÜChia
Hans Gabriel
Das Buch zum Apple-Writer II/lle
1986,155 S. , kart., DM 35,ISBN 3-7785-1234-X Begleitdiskette DM 44,ISBN 3-7785-1337-0
"Das Buch zum Apple Writer 11 / lle" wendet sich an alle, die dieses Textverarbeitu ngssystem schon einsetzen oder noch einsetzen wollen. In einzelnen , in sich geschlossenen Kapiteln erlernt der Leser alle Funktionen und erzielt schnelle Erfolgserlebnisse. Im ersten Kapitel werden typische Arbeitsstellungen der Textverarbeitung und ihre systematische Bearbeitung vorgestellt. Das zweite Kapitel stellt in logischen Funkti onsgruppen die Befehle vor, mit denen der Applewriter während der Textarbeit di rekt gesteuert werden kann. Kapitel 3 zeigt die Programmierung des Applewriters in der TextKommando-Sprache TKS (WPL). Dazu werden Beispiele analysiert. Auf der Beg leitdiskette zum Buch, die seperat bezogen werden kann , sind darüber hinaus umfangreiche SChwerpunkterklärungen entDr. Alfred Hüthig Verlag Im Weiher 10 6900 Heidelberg 1
halten , die über die HelpFunktion vom Benutzer abgerufen werden können. Eine kleine Adreßdatenbank mit der dazugehörigen Dienstprogrammen zur Pflege der Daten und zu ihrem Einsatz in Einzeiund Serienbriefen befindet sich ebenfalls auf Diskette. " Das Buch zum Apple Writer II / lle" behandelt sowohl die alte Programmversion für den Apple IIplus als auch die neue Ausgabe, die 128-kByte auf dem Apple lIe oder Apple Ilc unterstützt.
Ulrich Stiehl
ProDOS für Aufsteiger Band 1
2. geänderte Auflage 1985, 208 s., kart., DM 28,ISBN 3-7785-1098-3
"Apple ProDOS für Aufsteiger" ist der Nachfolgeband zu "Apple DOS 3.3 - Tips und Tricks" . ApplesoftProgrammierer, die unter DOS 3.3 gearbeitet haben, werden sich schnell an ProDOS gewöhnen, da ProDOS und DOS 3.3 in dieser Hinsicht weitgehend kompatibel sind . Dagegen müssen AssemblerProgrammierer völlig umdenken. Deshalb liegt das Schwergewicht dieses Nachfolgebandes auf der Assemblerprogrammierung und der minutiösen Darstellung der ProDOS-internen Systemadressen , die jedoch auch für Applesoft-Programmierer von großer Bedeutung sind. Im ersten Teil wird zunächst ein allgemeiner Überblick über das neue "Professional Disk Operation System" gegeben. Im Anschluß daran folgt eine Gegenüberstellung der Geschwindigkeit des Diskettenzugriffs. Dann wird die interne Speicherorganisation detailliert beschrieben (Boot-Vorgang , Zero-Page, ProDOS-Vektoren , Basic-System-Puffer, BasicSystem-Global-Page, Basic-
I~
Command-Handler, 1/ 0Vektoren , ProDOS-GlobalPage, Language-CardOrganisation, Interrupt, DiskDrivewr, Reboot-Programm usw.). Ebenso ausführlich wird di e externe Speicherorgan isation geschildert (Spuren , Sektoren, Blocks, DirectoryStruktur, Volume Bit Map, Datastrukturen usw.). Schließlich wird das MLI (Machine Language Interface) mit zahlreichen praktischen Anwendungsbeispielen erläutert. Insgesamt enthält ProDOS-Buch ca. 70 Seiten mit eigens für dieses Werk entwickelten Programmen. Im zweiten Teil werden die Basic-System-Befehle für Applesoft-Programmierer systematisch erläutert. Allerdings wird die Kenntn is von "Apple DOS 3.3" vorausgesetzt. .. ProDOS für Aufsteiger" ist deshalb nicht nur für Assemblersondern auch für fortgeschrittene Appelsoft-Programmi erer ein unentbehrliches Nachschlage-und Handbuch für die Programmierpraxis.
Dr. Alfred Hüthig Verlag Im Weiher 10 6900 Heidelberg 1
,u
.: