---------------------------------------- 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 Floppyprogrammierung in Assembler einsteigen. Im
letzten Monat hatten wir ja schon angesprochen, 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 ansprechen kann.
DIE ALTE METHODE
In der letzten Ausgabe des Floppy-Kurses
hatten wir gelernt, wie man ein File
öffnet, es zur Datenübertragung bereitmacht, Daten an es sendet und von ihm
empfängt, und es anschließend wieder
schließt. Die dort behandelte Arbeitsweise 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 Methode gingen wir immer folgendermaßen
vor:
1)" SETNAM" mit den Parametern für den
Filenamen aufrufen.
2)" SETPAR" mit den Datenkanalparametern aufrufen.
3) Mit " OPEN" das File öffnen 4 a) War das File eine Ausgabedatei, so
mussten wir " CKOUT" aufrufen.
4 b) War das File eine Eingabedatei, so mussten wir " CHKIN" aufrufen.
5 a) War das File eine Ausgabedatei, so
wurden die Daten mit Hilfe von " B-SOUT" geschrieben.
5 b) 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ückgestellt.
7) Das File wurde mit " CLOSE" geschlossen.
Wie gesagt, ist diese Methode die einfachste, wenn Sie ein einziges File lediglich Lesen oder Schreiben wollen.
Wenn Sie nun aber mehrere Files offenhalten und ansprechen wollen, oder aber
auf einem Kanal Lesen und Schreiben wollen ( 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 geschieht 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 Bildschirm 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 werden.
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, Tastatur, etc.) ansprechen können, weshalb
die Restriktionen dort etwas umständlicher 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 ersten Routinen erst einmal entschieden
werden muß, welche effektiven Ein-/ Ausgaberoutinen 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 meine 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 Kommunikationsschnittstelle zwischen C64 und
Floppy dient, werden auf Ihm Daten entweder vom Rechner zur Floppy oder umgekehrt hinund herbewegt. Die Verarbeitung dieser Daten ist dann dem jeweiligen Gegengerät überlassen, daß die Daten
empfangen hat. Noch dazu kann es vorkommen, 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 festgelegt werden welches der Geräte nun mit
welchem ( im Normalfall dem 64 er) kommu- nizieren soll. Hierzu dienen nun insgesamt sechs Betriebssystemroutinen.
Als erstes müssen wir wieder einmal ein
File auf die gewohnte Art und Weise öffnen. Zunächst übergeben wir die Filenamenparameter mit Hilfe von " SETNAM"( Akku= Länge des Namens, X/ Y= Zeiger auf Namensstring) . Anschließend muß " SETPAR" aufgerufen werden. Hierbei kommen Filenummer und Geräteadresse, wie gewohnt, in Akku und X-Register. Im Y-Register
wird die Sekundäradresse abgelegt. Jedoch müssen wir hier, anders als sonst, die gewünschte Sekundäradresse plus $60(= dez.96) übergeben. Dies hat Floppyinterne Gründe. Möchten wir also den Befehlskanal ansprechen, so muß die Sekundäradresse $6 F ( 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 gewünschten Gerätes im Akku ablegen.
Als nächstes muß dem Gerät an der anderen Seite mitgeteilt werden, welcher
seiner offenen Kanäle senden oder empfangen 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 speziellen IEC-Ein-/ Ausgaberoutinen, die
ich oben schon ansprach. Sie können sie
genauso wie " BASIN" und " BASOUT" benutzen. 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 werdeb muß.
Haben Sie die Einoder Ausgabe beendet, so müssen Sie das entsprechende Empfangs-, bzw. Sendegerät wieder in den
Wartezustand zurückbringen. Dies geschieht über die Routinen " UNTALK" und" UNLIST" . Die erstere müssen Sie nach
dem Empfang, die letztere nach dem Senden 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 Filekanal und teilen der Floppy mit, daß sie
Daten empfangen soll (" LISTEN" und
" SECLST" aufrufen) . Nun senden Sie mittels " IECOUT" den Befehlsstring. Anschließ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 Befehlskanal 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 ansprechen, müssen Sie einfach den entsprechenden Öbertragungsmodus festlegen und
seine Sekundäradresse an die Floppy
schicken. Denken Sie immer daran, daß
Sie nach jeder Leseoder Schreiboperation 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 Programmbeispielen, 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üssen wir lediglich den Aufruf von " CH-KIN/ CKOUT" mit dem von " TALK/ SECTALK" oder " LISTEN/ SECLIST" ersetzen. Der Aufruf von " CLRCH" am Ende der Öbertragung
muß mit einem " UNTALK" bzw." UNLIST" ersetzt werden. Desweiteren muß den Sekundä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 miteinander 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 ergibt, ist, daß Sie nun problemlos, während des Arbeitens mit einem File, Statusmeldungen 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. Umgekehrt wird bei BASIN von der Tastatur, und nicht etwa aus dem offenen File gelesen.
Als Beispiel für eine solche Anwendung
möchte Ich Ihnen das Auslesen des Fehlerkanals 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 grafikschen Anzeige dekodieren. Dies ist
ein hervorragendes Beispiel um die Benutzung der neuen I/ O-Routinen zu demonstrieren 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 reserviert. 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 vierten 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 bedeutet, 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 Befehlskanal 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!