---------------------------------------- Floppy-Kurs: "Es rappelt in der Kiste..." (Teil 8) ----------------------------------------
Herzlich Willkommen zum achten Teil des Floppy-Kurses. In diesem Monat wollen wir noch etwas weiter in die Floppypro- grammierung in Assembler einsteigen. Im letzten Monat hatten wir ja schon ange- sprochen, wie man ein File öffnet und mit ihm kommuniziert, sowie man Files lädt und speichert. Diesmal will ich Ihnen eine andere, effektiviere Methode zeigen, mit der man die Floppy anspre- chen kann. DIE ALTE METHODE In der letzten Ausgabe des Floppy-Kurses hatten wir gelernt, wie man ein File öffnet, es zur Datenübertragung bereit- macht, Daten an es sendet und von ihm empfängt, und es anschließend wieder schließt. Die dort behandelte Arbeits- weise war die einfachste, die man zum reinen Lesen oder Schreiben eines Files anwendet. Es gibt jedoch eine weitere Methode Files anzusprechen. Diese ist zwar ein wenig umständlicher, dafür aber schneller und weitaus flexibler. Rekapitulieren wir: Nach der ersten Me- thode gingen wir immer folgendermaßen vor: 1 ) "SETNAM" mit den Parametern für den Filenamen aufrufen. 2 ) "SETPAR" mit den Datenkanalparame- tern aufrufen. 3 ) Mit "OPEN" das File öffnen 4a) War das File eine Ausgabedatei, so mussten wir "CKOUT" aufrufen. 4b) War das File eine Eingabedatei, so mussten wir "CHKIN" aufrufen. 5a) War das File eine Ausgabedatei, so wurden die Daten mit Hilfe von "B- SOUT" geschrieben. 5b) War das File eine Eingabedatei, so wurden die Daten mit Hilfe von "BA- SIN" gelesen. 6 ) Abschließend wurde mittels "CLRCH" die Standardausgabe wieder zurückge- stellt. 7 ) Das File wurde mit "CLOSE" geschlos- sen. Wie gesagt, ist diese Methode die ein- fachste, wenn Sie ein einziges File le- diglich Lesen oder Schreiben wollen. Wenn Sie nun aber mehrere Files offen- halten und ansprechen wollen, oder aber auf einem Kanal Lesen und Schreiben wol- len (so wie das beim Befehlskanal unter Mitbenutzung von Pufferkanälen oft der Fall ist), so versagt diese Methode. Das liegt daran, daß Sie mit der einfachen Methode eigentlich nicht wirklich mit den Dateien kommunizieren. Dies ge- schieht dann nämlich mit einem Umweg über das Betriebssystem. Das Aufrufen von "CKOUT" entspricht zum Beispiel dem Basic-Befehl "CMD". Sie leiten damit die Daten, die normalerweise auf dem Bild- schirm ausgegeben werden, auf den Floppykanal um. Nun ist es aber wiederum nicht so einfach, einen zum Ausgabekanal erklärten Filekanal, als Eingabekanal zu benutzen. Ein folgendes "CHKIN" zeigt nämlich keine Wirkung. Auch wenn Sie zwei Files offenhalten, so funktioniert das Umschalten zwischen diesen beiden Files nicht immer. Der Grund dafür liegt in der Art und Weise wie die Standard- Ein/Ausgabefiles im C64 verwaltet wer- den.
DIE NEUE METHODE
Um nun effizienter mit der Floppy zu kommunizieren, müssen wir auf spezielle Betriebssystemroutinen zurückgreifen, die eigens für die Datenkommunikation mit der Floppy (bzw. dem IEC-Bus, an dem Floppy und Drucker angeschlossen sind), dienen. Diese Routinen werden im Prinzip auch bei Verwendung der ersten Methode vom Betriebssystem benutzt, jedoch muß ein Standard-Kanal eben auch andere, virtuelle, Geräte (wie Bildschirm, Ta- statur, etc.) ansprechen können, weshalb die Restriktionen dort etwas umständli- cher sind. Deshalb ist eine Ausgabe über BASOUT, oder die Eingabe über BASIN, auch immer langsamer, als wenn Sie die entsprechenden I/O-Routinen für den IEC-Bus benutzen, da bei den beiden er- sten Routinen erst einmal entschieden werden muß, welche effektiven Ein-/Aus- gaberoutinen nun wirklich benutzt werden müssen (in unserem Fall nämlich die IEC-Busroutinen). Kommen wir nun jedoch endlich zu den neuen Routinen und deren Funktionsprin- zip. Hierzu müssen wir uns zunächst noch einmal verdeutlichen, daß die Floppy im Prinzip ein eigenständiger Computer ist, der nichts anderes tut, als darauf zu warten, daß Befehle über den IEC-Bus kommen, um sie auszuführen. Hierbei mei- ne ich nicht die Floppy-Befehle, wie wir sie bisher kennengelernt haben. Diese stellen wiederum eine höhere Ebene von Befehlen dar. Da der IEC-Bus als Kommu- nikationsschnittstelle zwischen C64 und Floppy dient, werden auf Ihm Daten ent- weder vom Rechner zur Floppy oder umge- kehrt hin- und herbewegt. Die Verarbei- tung dieser Daten ist dann dem jeweili- gen Gegengerät überlassen, daß die Daten empfangen hat. Noch dazu kann es vorkom- men, daß sich bis zu 7 Geräte (der C64, max. 2 Drucker und max. vier Floppys) über ein und denselben Bus miteinander unterhalten müssen. In dem Fall muß vor einer Datenübertragung natürlich festge- legt werden welches der Geräte nun mit welchem (im Normalfall dem 64er) kommu- nizieren soll. Hierzu dienen nun insge- samt sechs Betriebssystemroutinen. Als erstes müssen wir wieder einmal ein File auf die gewohnte Art und Weise öff- nen. Zunächst übergeben wir die Filena- menparameter mit Hilfe von "SETNAM" (Ak- ku=Länge des Namens, X/Y=Zeiger auf Na- mensstring). Anschließend muß "SETPAR" aufgerufen werden. Hierbei kommen File- nummer und Geräteadresse, wie gewohnt, in Akku und X-Register. Im Y-Register wird die Sekundäradresse abgelegt. Je- doch müssen wir hier, anders als sonst, die gewünschte Sekundäradresse plus $60 (=dez. 96) übergeben. Dies hat Floppyin- terne Gründe. Möchten wir also den Be- fehlskanal ansprechen, so muß die Se- kundäradresse $6F (dez. 111) übergeben werden. Möchten wir ein PRG-File lesen, so müssten wir den Wert $60 übergeben, etc. Zuletzt wird wieder wie üblich das File mittels "OPEN" geöffnet. Soweit also nichts Neues. Nun müssen wir uns, wie vorher auch, verdeutlichen, ob die Floppy senden, oder empfangen soll. Anstelle von "CHKIN" oder "CKOUT" müssen diesmal jedoch andere Routinen benutzt werden. Möchten wir Daten empfangen, so soll die Floppy mit uns "reden". Deshalb heißt die entsprechende Routine, die sie dazu auffordert uns Daten zuzusenden "TALK" (engl. "reden"). Wollen wir Daten senden soll die Floppy uns "zuhören". Die hierfür gedachte Unterroutine heißt "LISTEN" (engl. "hören"). Da es, wie oben schon einmal beschrieben, bis zu 6 Geräte geben kann, die uns zuhören oder mit uns reden sollen, muß mit "TALK" oder "LISTEN" auch mitgeteilt werden, welches der Geräte nun für uns bereit sein soll. Hierzu müssen Sie vor Aufruf der Routinen die Geräteadresse des ge- wünschten Gerätes im Akku ablegen. Als nächstes muß dem Gerät an der ande- ren Seite mitgeteilt werden, welcher seiner offenen Kanäle senden oder emp- fangen soll. Hierzu muß die Sekundär- adresse an das Gerät übermittelt werden. Dies geschieht über die Routinen "SECTLK" und "SECLST". Beide verlangen die gewünschte Sekundäradresse (wieder plus $60) als Parameter im Akku. "SECTLK" müssen Sie nach einem "TALK" aufrufen, "SECLST" nach einem "LISTEN". Nun ist alles vorbereitet, um Daten zu lesen oder zu schreiben. Dies erledigen Sie nun am besten mit den beiden spe- ziellen IEC-Ein-/Ausgaberoutinen, die ich oben schon ansprach. Sie können sie genauso wie "BASIN" und "BASOUT" benut- zen. Zum Lesen von Daten benutzen Sie die Routine "IECIN", die das gelesene Byte im Akku zurückgibt. Zum Schreiben benutzen Sie "IECOUT", der das zu schreibende Byte im Akku übergeben wer- deb muß. Haben Sie die Ein- oder Ausgabe beendet, so müssen Sie das entsprechende Emp- fangs-, bzw. Sendegerät wieder in den Wartezustand zurückbringen. Dies ge- schieht über die Routinen "UNTALK" und "UNLIST". Die erstere müssen Sie nach dem Empfang, die letztere nach dem Sen- den von Daten benutzen. Dies müssen Sie auch immer dann tun, wenn Sie anschlie- ßend auf dem selben Kanal eine andere Operation ausführen wollen (z.B. Befehl an Befehlskanal senden und anschließend Floppystatus auslesen). Wenn Sie mit Ihrer Operation nun fertig sind, so können Sie den zuvor geöffneten Filekanal wieder schließen. Wie Sie sehen ist diese Methode etwas aufwendiger. Dafür aber können Sie nun problemlos den Befehlskanal öffnen und z.B. den "Memory-Read"-Befehl ("M-R") benutzen. Hierbei öffnen Sie einen File- kanal und teilen der Floppy mit, daß sie Daten empfangen soll ("LISTEN" und "SECLST" aufrufen). Nun senden Sie mit- tels "IECOUT" den Befehlsstring. An- schließend setzen Sie die Floppy wieder in der Normalstatus zurück, indem Sie "UNLIST" aufrufen. Hiernach können Sie nun die zuvor verlangten Daten vom Be- fehlskanal abholen. Senden Sie einfach ein "TALK" und "SECTLK" und lesen Sie die Daten mit "IECIN" ein. Abschließend muß die Floppy wieder mit "UNTALK" in den Wartezustand geschickt werden und wir können das File schließen. Desweiteren ist das Bedienen von zwei offenen Files nun weitaus besser mö- glich. Bevor Sie eines dieser Files ans- prechen, müssen Sie einfach den entspre- chenden Öbertragungsmodus festlegen und seine Sekundäradresse an die Floppy schicken. Denken Sie immer daran, daß Sie nach jeder Lese- oder Schreibopera- tion ein "UNTALK" oder "UNLIST" senden müssen, damit die Floppy auf weitere Befehle reagiert. Hier nun noch die Einsprung-Adressen der neuen I/O-Routinen:
LISTEN: $FFB1 TALK: $FFB4 SECLST: $FF93 SECTLK: $FF96 UNLIST: $FFAE UNTALK: $FFAB IECOUT: $FFA8 IECIN: $FFA5 PROGRAMM-BEISPIELE
Kommen wir nun noch zu einigen Programm- beispielen, die Ihnen die Benutzung der neuen I/O-Routinen erläutern sollen. Die Routinen aus Beispiel 1 und 2 finden Sie, als Hypra-Ass Quellcode, auf dieser MD unter dem Namen "FK.IO2.S". Der Quellcode für Beispiel 3 steht im File "FK.SHOWBAM.S". Da es sich dabei um ein eigenständiges Programm handelt, existiert hierzu auch noch ein, durch 'RUN' startbares, File namens "FK.SHOW- BAM". 1) LESEN UND SCHREIBEN EINES FILES Zunächst einmal möchte ich Ihnen zeigen, wie die beiden Routinen "READFILE" und "WRITEFILE" aus dem letzten Kursteil in der neuen Methode aussehen. Hierbei müs- sen wir lediglich den Aufruf von "CH- KIN/CKOUT" mit dem von "TALK/SECTALK" oder "LISTEN/SECLIST" ersetzen. Der Au- fruf von "CLRCH" am Ende der Öbertragung muß mit einem "UNTALK" bzw. "UNLIST" ersetzt werden. Desweiteren muß den Se- kundäradressen beim Üffnen der Wert $60 hinzuaddiert werden ('$60' bei ReadFile, '$61' bei WriteFile). Der Rest des Programms sollte sich von selbst erklären. Damit man die alte und neue Version der Routinen nicht mitei- nander verwechselt, heißen die neuen Versionen "IECREAD" und "IECWRITE". Die Parameter, die beim Aufruf übergeben werden müssen, sind dieselben wie bei den alten Versionen: IECREAD stx $fb ;Startadresse in sty $fc ; Zeiger ablegen.
ldx #$34 ;Zeiger auf ldy #$03 ; Filenamen jsr setnam ; setzen. lda #01 ;Fileparameter ldx #08 ; setzen ldy #$60 ; ($60=PRG Lesen) jsr setpar jsr open ;File öffnen lda #08 ;"Gerät Nr. 8: jsr talk ; rede bitte!" lda #$60 ;"Und zwar auf Se- jsr sectlk ; kundäradr. $60)!" ldy #00 ;Offset=0 loop1 jsr iecin ;Zeichen lesen sta ($fb),y; und ablegen inc $fb ;Zeiger bne l1 ; um 1 inc $fc ; erhöhen l1 lda $90 ;Ende erreicht? beq loop1 ;Nein, dann weiter!
lda #08 ;Sonst: "Gerät jsr untalk ; Nr.8:Ruhe bitte!" lda #01 ;File jmp close ; schließen ;*************************************** IECWRITE stx $fb ;Startadresse in sty $fc ; Zeiger ablegen
ldx #$34 ;Filenamen ldy #$03 ; setzen jsr setnam lda #01 ;Fileparameter ldx #08 ; setzen ldy #$61 ; ($61=PRG schr.) jsr setpar jsr open ;File öffnen lda #08 ;"Gerät Nr8: Hör' jsr listen ; mir bitte zu!' lda #$61 ;"Und zwar auf Sek.
jsr seclst ; Adr. $61!")
ldy #00 ;Offset=0 loop2 lda ($fb),y;Zeichen holen jsr iecout ; und abschicken inc $fb ;Zeiger bne l2 ; um 1 inc $fc ; erhöhen l2 lda $fe ;Und mit cmp $fc ; Endadresse bne loop2 ; vergleichen lda $fd ;Wenn ungleich cmp $fb ; dann weiter bne loop2 lda #08 ;"Gerät Nr.8: jsr unlist ; Bin fertig!" lda #01 ;File jmp close ; schließen 2) FLOPPYSTATUS ANZEIGEN
Ein weiterer Vorteil, der sich aus der Benutzung der direkten IEC-Routinen er- gibt, ist, daß Sie nun problemlos, wäh- rend des Arbeitens mit einem File, Sta- tusmeldungen auf dem Bildschirm ausgeben können. Da die Standard Ein-/Ausgabe ja nicht verändert wurde, erscheinen Texte, die mit BSOUT ausgegeben werden sollen, auch weiterhin auf dem Bildschirm. Umge- kehrt wird bei BASIN von der Tastatur, und nicht etwa aus dem offenen File ge- lesen. Als Beispiel für eine solche Anwendung möchte Ich Ihnen das Auslesen des Feh- lerkanals der Floppy zeigen. Hierzu muß lediglich der Befehlskanal geöffnet, und die Fehlermeldung, die im ASCII-Code von der Floppy generiert und übermittelt wird, Zeichen für Zeichen ausgelesen und auf dem Bildschirm ausgegeben werden. Ich denke, die Routine erklärt sich von selbst:
ERRCHN lda #00 ;Länge Filename=0 jsr setnam ; für "Kein Name" lda #01 ;Fileparameter ldx #08 ; setzen ldy #$6f ; (=Befehlskanal) jsr setpar jsr open ;Filekanal öffnen lda #08 ;Floppy Nr.8 zum jsr talk ; Senden auffordern lda #$6f ;Und zwar auf Kanal jsr sectlk ; mit Sek.Adr. $6F ecloop1 jsr iecin ;Zeichen lesen jsr bsout ;Und auf dem Bild- schirm ausgeben lda $90 ;Fileende erreicht? beq ecloop1; Nein, also weiter lda #08 ;Floppy Nr.8 jsr untalk ; zurücksetzen lda #01 ;Und Befehlskanal jmp close ; schließen
3) BAM ANZEIGEN Als Nächstes wollen wir ein Programm schreiben, daß uns anzeigt, welche Blocks einer Diskette belegt sind, und welche nicht. Hierzu müssen wir die BAM ("Block Availability Map"), die im Disk-Header-Block (Track 18 Sektor 0) zu finden ist, auslesen und zu einer gra- fikschen Anzeige dekodieren. Dies ist ein hervorragendes Beispiel um die Be- nutzung der neuen I/O-Routinen zu de- monstrieren und gleichzeitig zu zeigen, wie man mit der BAM umgeht. Sie erinnern sich vielleicht noch an deren Aufbau. Ich hatte ihn in Teil 5 dieses Kurses besprochen: Im Disk-Header-Block sind die Bytes 4 bis einschließlich 143 für die BAM re- serviert. Hierbei zeigen jeweils 4 Bytes in Folge die Blockbelegung für einen Track an. Im ersten Byte steht dabei die Gesamtanzahl der freien Blocks dieses Tracks. Die Bits des zweiten Bytes ko- dieren die Belegung der Sektoren 0-7, die Bits des dritten Bytes die Belegung der Sektoren 8-15 und die Bits des vier- ten Bytes die Belegung der Sektoren 16- 23. Hat ein Track weniger Sektoren, als im vierten Byte angezeigt werden, so sind die restlichen Bits dieses Bytes unbenutzt (so z.B. immer die letzten zwei Bits, da es ja nie mehr als 21 Tracks gibt). Ein gesetztes Bit bedeu- tet, daß der entsprechende Sektor frei ist, ein gelöschtes Bit, daß er belegt ist. Wollen wir einmal klären, welche Dinge zur Lösung des obigen Problems notwendig sind. Zunächst müssen wir den Befehlska- nal und anschließend einen Pufferkanal öffnen. Nun muß der Befehl zur Floppy gesandt werden, der den Block 18/0 in den geöffneten Puffer liest. Ist dies geschehen, müssen wir nur noch auf das vierte Byte des Puffers positionieren (dort beginnt ja die BAM) und die vier Belegungs-Bytes für jeden Track einlesen und darstellen. Bitte Teil 2 des Kurses laden!