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 e