C 64/VC 20
Floppy-Kurs

In die Geheimnisse der Floppy eingetaucht (Teil 2)

Diese Folge befaßt sich mit dem Befehlssatz der VC 1541 und deren Meldungen an den Computer. Sie werden erkennen, daß Sie neben Ihrem C 64 noch einen anderen vollständigen Computer vor sich haben, der nicht nur als einfaches und »dummes« Peripheriegerät verstanden werden will.

Sicherlich machte sich mancher Floppybesitzer, der ein schnelleres Peripheriegerät als die Datasette haben wollte, schon seine Gedanken über den Preis der VC 1541: »Die kostet ja mehr als der Computer!«. In der Tat ist die VC 1541 von dieser Seite her betrachtet nicht gerade günstig, wer sich jedoch schon intensiver mit ihr beschäftigt hat, wird eine Eigenart festgestellt haben, die sie mit allen CBM-Floppys teilt: Es handelt sich hier um sogenannte Floppystationen, nicht nur um Laufwerke. Das bedeutet, diese Geräte besitzen ein eigenes Betriebssystem (DOS) und eigene Mikroprozessoren. Sie arbeiten völlig unabhängig vom Computer und dessen Speicher. Der Vorteil liegt auf der Hand: Die Floppy beansprucht weder Speicherplatz noch Rechenzeit des Computers, außer beim direkten Datenaustausch. Als Beispiel betrachte man den Befehl »N:« (Formatieren). Während der Formatierung steht der Computer zur (fast) freien Verfügung, da dieser Vorgang nur floppyintern abläuft und sich der C 64 mit READY meldet, während die 1541 noch arbeitet.

Wir wollen uns jedoch nur den Direktzugriffsbefehlen und den Speicherbefehlen widmen; auch übergehen wir die im Commodore-Handbuch nicht erwähnte relative Datenspeicherung, über die in anderen Ausgaben schon ausführlich gesprochen wurde. Uns sollen nur die Befehle beschäftigen, die uns zur willkürlichen Manipulation von Floppystation und Disketten nützen.

Zur Beruhigung: Ein Beschädigen der 1541 durch direkte Eingriffe in das DOS ist nicht zu befürchten, auch wenn es passieren kann, daß sich die Floppy nur durch Aus-/ Einschalten wieder in den Normalzustand versetzen läßt. Haben Sie übrigens einmal, wie in der letzten Folge empfohlen, das Formatkennzeichen einer Diskette verändert? Sie werden sicherlich bemerkt haben, daß sich danach nichts mehr auf Ihre Diskette schreiben läßt. Mit diesem Trick, der die gleichen Folgen wie das Anbringen einer Schreibschutzplakette an der Diskette hat, können Sie sich also ganz einfach Ihre Diskette gegen unbeabsichtigtes Löschen sichern. ACHTUNG: Diese Methode funktioniert natürlich nicht, wenn neu formatiert werden soll; hiergegen hilft nur das Anbringen einer Schreibschutzplakette!

Die Floppystation verfügt über, außer den schon bekannten Befehlen zur Diskettenorganisation, noch eine ganze Anzahl weiterer Befehle, mit denen sich ungeahnte Möglichkeiten ergeben, zum Beispiel Herstellen eines eigenen Diskettenformats, Leseschutz von Disketten, Programmschutz, Modifikation der Lade- und Saveroutinen und, und… Dafür ist es allerdings nötig, daß wir diese Befehle Schritt für Schritt kennen lernen, bevor wir auf die Tricks der Profis, die Manipulationen des DOS und den gezielten Eingriff in den Programmablauf der Floppystation zu sprechen kommen. Dafür ist allerdings das Beherrschen des C 64 und der Maschinensprache unerläßlich. So lohnt es sich unter Umständen, nachdem man aus Basic nichts mehr herausholen kann, den Einstieg in die Assemblerprogrammierung zu wagen. Sehr gute Literatur dafür ist vorhanden. Aber diesmal wollen wir uns noch auf Basic beschränken, um Sie mit dem Befehlssatz der Floppy vertraut zu machen.

Wie schon erwähnt, handelt es sich bei der 1541 um einen vollständigen Computer, der ebenso wie Ihr C 64 RAM und ein Betriebssystem (DOS) im ROM besitzt.

Die genaue Aufteilung ist in Bild 1 zu sehen. Jetzt soll uns nur der RAM-Bereich interessieren (Bild 2). Nicht nur auf der Diskette, sondern auch im RAM werden Speicherbereiche in Abschnitte zu jeweils 256 Byte aufgeteilt. Sie heißen dann nicht mehr BLOCKS sondern PAGES (Seiten). Das RAM der 1541 umfaßt nun genau 8 PAGES, durchnumeriert von 0 bis 7, insgesamt als 2 KByte. Die Page Nr. 0 (auch Zero-Page genannt) wird hier, wie auch im C 64, vom Betriebssystem als Arbeitsspeicher benutzt und steht uns deshalb nicht zur freien Verfügung. Ähnlich verhält es sich mit den Pages 1 und 2. Die Pages 3 bis 7 stellen sogenannte Pufferspeicher dar; hier werden alle Daten, die von der Diskette gelesen beziehungsweise auf sie geschrieben werden, zwischengespeichert, da nur blockweise gelesen oder geschrieben werden kann.

Bild 1. Die Speicheraufteilung der 1541
Bild 2. So ist das 2 KByte RAM der 1541 aufgeteilt.

Soll zum Beispiel nur ein einziges Byte auf der Diskette geändert werden, so wird erst der gesamte Block in einen der 5 Pufferspeicher gelesen, dort abgeändert und schließlich komplett wieder zurückgeschrieben. Aus diesen Gründen ist es also notwendig, daß wir uns vor einem Direktzugriff einen der Puffer reservieren, in dem dann gearbeitet wird.

Mit Hilfe des »Open«-Befehls eröffnen wir einen Direktzugriffskanal. Die Syntax lautet wie folgt: OPEN fn, gn, kn, ”#”

Hierbei bedeuten:

Diese Abkürzungen werden wir im folgenden immer verwenden! Ein Beispiel: OPEN 1, 8, 2, ”#”

Diese Anweisung eröffnet im Computer ein File mit der Nummer 1, adressiert als Gerät die Floppy (Nummer 8) und reserviert in der 1541 einen Kanal (Nummer 2), dem ein Puffer zugeordnet wird. Mit den floppyinternen Kanälen verhält es sich wie folgt: Es stehen insgesamt 16 Kanäle zur Verfügung. Hierbei sind Kanal 0 und 1 für LOAD und SAVE reserviert, Kanal 15 ist der Kommandokanal, den Sie bisher immer benutzt haben, um Befehle (zum Beispiel Formatieren) an die Floppy zu senden und die Fehlermeldungen der Floppy zu empfangen.

Für unsere Zwecke stehen also noch die Kanäle 2 bis 14 zur Verfügung. In unserem Fall reserviert die Floppy den nächsten freien Puffer. Will man jedoch einen bestimmten Puffer reservieren, etwa um dort ein Maschinenprogramm abzulegen, so ist es notwendig, der 1541 mitzuteilen, welcher Puffer gewünscht wird: OPEN1,8,2,"#1"

Es ist hier allerdings zu beachten, daß der gewählte Puffer nicht schon belegt ist; in diesem Fall gibt die Floppy eine Fehlermeldung aus. Wollen Sie an dieser Stelle mehr über das Auslesen der Fehlermeldungen und deren Bedeutung wissen, können wir Sie hier beruhigt auf das Commodore-Handbuch verweisen. Im allgemeinen sind Puffer 4 für die BAM und Puffer 3 für das Directory reserviert. Haben Sie die Wahl des Puffers der Floppy überlassen, so erfahren Sie die gewählte Nummer durch Auslesen des soeben geöffneten Direktzugriffskanals: 10 OPEN 1,8,2,”#" 20 GET#1,D$ 30 D = ASC (D$ + CHR$(0)) 40 REM Puffernummer in D

Die BLOCK-Befehle

  1. Der BLOCK-READ-Befehl (B-R):

    Mit dem BLOCK-READ-Befehl liest man jeden beliebigen Block von Diskette in einen vorher reservierten Puffer. Die Syntax lautet: PRINT#fn,"B-R";kn;dn;t;s

    • dn — Drivenummer (immer 0)
    • t — Tracknummer
    • s — Sektornummer
    Beispiel: PRINT#15,"B-R 2 0 18 0”

    Diese Befehlsfolge liest den Block 18,0 von der Diskette in den oben reservierten Puffer. Wie man sieht, können anstelle der CHR$-Codes feste Zahlenwerte in den Befehlsstring mit übernommen werden. Das ganze hat bloß einen kleinen Schönheitsfehler. Mit dem B-R-Befehl läßt sich das erste Byte eines Blocks nicht lesen. Deshalb benutzt man normalerweise anstatt des B-R-Befehls den U1-Befehl. Dieser hat exakt die gleiche Syntax und kann in jedem Fall benutzt werden: PRINT#15,"U1 2 0 18 0” Auf diese USER-Befehle kommen wir später zurück. Mit einer GET#-Schleife lassen sich nun die einzelnen Bytes in den Computer einlesen.

  2. Der BLOCK-WRITE-Befehl (B-W):

    Hiermit lassen sich die Daten aus dem reservierten Puffer wieder auf die Diskette schreiben. Syntax: PRINT#fn,”B-W”;kn;dn;t;s

    Beispiel: PRINT#15,"B-W 2 0 18 0”

    Natürlich gibt es analog zum B-R einen USER-Befehl ; U2.
    Beispiel: PRINT#15,"U2 2 0 18 0".

  3. Der BUFFER-POINTER-Befehl (B-P):

    Für jeden Puffer gibt es einen Zeiger, den BUFFER-POINTER. Dieser zeigt auf das aktuelle Byte im Puffer und wird bei jedem Datenzugriff um Eins erhöht, damit man alle 256 Bytes eines Blocks der Reihe nach lesen kann. Dieser Pointer wird mit dem B-P-Befehl gezielt auf bestimmte Bytes positioniert, wenn man nur einzelne Werte und nicht den gesamten Block lesen will. Syntax: PRINT# fn,"B-P"; kn; position

    Beispiel:
    Wir möchten in die Variable A den Wert des 123. Bytes von Block 1;16 einlesen: 10 OPEN15,8,15 20 OPEN1,8,2,"#" 30 PRINT#15,"U1 2 0 1 16” 40 PRINT#15,"B-P2 122” 50 GET#1,A$ 60 A = ASC(A$ + CHR$(0)) Als weiteres Beispiel dient Listing 1.

  4. Der BLOCK-ALLOCATE-Befehl (B-A):

    Wenn Sie im Direktzugriffsverfahren eine Diskette beschreiben, muß in der BAM danach auch verzeichnet werden, daß die entsprechenden Blocks mit Daten gefüllt sind und nicht mehr überschrieben werden dürfen. Dazu dient der B-A-Befehl, der jeden beliebigen Block in der BAM als belegt kennzeichnet. Die Syntax lautet: PRINT#fn,"B-A";dn;t;s

    Beispiel: PRINT#15,"B-A0 1 16” kennzeichnet Block 1;16 als belegt; war dieser Block schon belegt, meldet sich die Floppy mit der Fehlermeldung »65,NO BLOCK,XX,YY«; wobei XX und YY die Track- und Sektornummer des nächsten freien Blocks angeben.

  5. Der BLOCK-FREE-Befehl (B-F):

    Dieser ist das genaue Gegenstück zum B-A-Befehl; er deklariert einmal belegte Blöcke wieder als frei für einen weiteren Zugriff. Seine Syntax ist identisch mit der des B-A-Befehls.

  6. Der BLOCK-EXECUTE-Befehl (B-E):

    Dieser Befehl nimmt eine Sonderstellung ein. Er gleicht im Prinzip dem B-R-Befehl; nur mit dem zusätzlichen Effekt, daß der eingelesene Block im Puffer als Maschinenprogramm gestartet wird.

Zur Vertiefung der Block-Befehle sei noch auf die Listings 2 bis 5 hingewiesen, welche die eben besprochenen Anwendungen noch an praktischen Beispielen verdeutlichen.

Die MEMORY-Befehle

  1. Der MEMORY-READ-Befehl (M-R):

    Dieser Befehl entspricht haargenau dem PEEK-Befehl in Basic. Mit ihm können Sie jede beliebige Speicherstelle der Floppy auslesen. Syntax: PRINT#fn,"M-R";CHR$(adl);CHR$ (adh);CHR$(n)

    • adl = Low-Byte
    • adh = High-Byte
    • n = Anzahl (0 bis 255)

    Abgeholt werden die gelesenen Daten ebenfalls über den Kommandokanal mit GET#.

    Beispiel: Lesen der beiden ID-Zeichen im ASCII-Format der zuletzt initialisierten Diskette: 10 OPEN15,8,15 20 PRINT#15,"M-R"CHR$(18)CHR$ (0)CHR$(2) 30 GET#15,A$,B$ 40 PRINTA$;B$

    Diese Routine liest die Zero-Page Adressen 18 und 19, in denen die entsprechenden Werte gespeichert sind. In Tabelle 1 sind einige der wichtigsten Zero-Page Adressen aufgeführt.

  2. Der MEMORYWRITE-Befehl (M-W):

    Dieses Kommando kann als POKE-Befehl in den Floppy-Speicher angesehen werden. Die Syntax ist hier wie folgt: PRINT#fn, "M-W";CHR$(adl)CHR$ (adh)CHR$(n)CHR$(data1)CHR$(data2)…

  3. Der MEMORY-EXECUTE-Befehl (M-E):

    Auch dieser Befehl ist äquivalent zu einem Basic-Befehl, dem SYS-Befehl. Mit ihm kann man also ein Maschinenprogramm an einer beliebigen Stelle im Floppy-Speicher ausführen. Syntax: PRINT#fn,"M-E"CHR$(adl)CHR$(adh). Siehe auch Listing 7.

Die USER-Befehle

Die USER-Befehle stellen eine Erweiterung des Befehlssatzes dar, der fast ausschließlich der Bequemlichkeit dient. Ul und U2 wurden schon besprochen, sie ersetzen B-R und B-W. Die Befehle U3 bis U8 dienen dem Start eines Maschinenprogramms im Floppy-Speicher, dessen Anfangsadressen in einer Tabelle abgelegt sind, so entsprechen:

Mit den Kenntnissen über den Befehlssatz der VC 1541 dürfte es Ihnen nun keine Schwierigkeiten mehr bereiten, sich das Programm EDDI einmal zu Gemüte zu führen. Das einzig Besondere daran sind die Routinen zum Lesen und Schreiben eines Blocks, die aus Geschwindigkeitsgründen in Maschinensprache geschrieben sind. Ein großer Teil der in diesen Folgen erwähnten Informationen ist auch im Commodore-Handbuch enthalten, nur sind dort oft Fehler.

Wir wollen uns für diese Folge von Ihnen verabschieden, nicht ohne Sie dringend dazu anzuhalten zu probieren.

(Schramm/Schneider/gk)
100 rem aenderung von id, formatkenn-
101 rem zeichen & leerzeichen zwischen
102 rem diesen beiden.(insg. 5 zeichen)
103 rem bsp: alte id :xy 2a
104 rem             id^  ^formatkennz.
105 rem kann auf     :hallo
106 rem geaendert werden. das leerz.
107 rem wird hier zum ersten 'l'
108 rem wirkt sich nur auf direct. aus!
109 :
110 open 15,8,15,"i":open1,8,2,"#"
120 print#15,"u1 2 0 18 0"
130 print#15,"b-p 2 162"
140 get#1,a$,b$,c$,d$,e$
150 print a$;b$;c$;d$;e$
160 input"neu:";n$
170 print#15,"b-p 2 162"
180 print#1,n$;
190 print#15,"u2 2 0 18 0"
200 print#15,"i"
210 close 8:close 15
Listing 1. Änderung der ID und des Formatkennzeichens
1000 rem unterprogramm 1
1001 rem lesen eines eintrages aus dem
1002 rem directory (alle 30 bytes !!!)
1003 rem in die variable dd$
1004 rem uebergabeparameter:
1005 rem mm=nummer des eintrages der
1006 rem    gelesen werden soll
1007 :
1008 :
1009 :
1010 open 15,8,15,"i":open8,8,8,"#"
1020 nn$="":fori=1to30:nn$=nn$+chr$(0):nexti
1030 xx=int((mm-1)/8)
1040 print#15,"u1 8 0 18 0"
1050 forzz=1toxx+1
1060 print#15,"b-p 8 0"
1070 get#8,tt$:tt=asc(tt$+chr$(0))
1080 get#8,ss$:ss=asc(ss$+chr$(0))
1090 if tt=0 then dd$=nn$:goto1170
1100 print#15,"u1 8 0";tt;ss
1110 nextzz
1120 pp=mm-(xx*8):pp=(pp-1)*32+2
1130 print#15,"b-p 8";pp
1140 forzz=1 to 30:get#8,zz$
1150 ifzz$=""thenzz$=chr$(0)
1160 dd$=dd$+zz$:nextzz
1170 close 8:close 15
1180 return
Listing 2. Unterprogramm 1. Lesen eines Eintrages aus dem Directory.
2000 rem unterprogramm 2
2001 rem schreiben eines eintrages in
2002 rem das directory (30 bytes !!!)
2003 rem uebergabeparameter:
2004 rem mm=nummer des eintrages der
2005 rem    geschrieben werden soll
2006 rem dd$=directoryeintrag
2007 :
2008 :
2009 :
2010 open 15,8,15,"i":open8,8,8,"#"
2020 xx=int((mm-1)/8)
2030 print#15,"u1 8 0 18 0"
2040 forzz=1toxx+1
2050 print#15,"b-p 8 0"
2060 get#8,t$:tt=asc(t$+chr$(0))
2070 get#8,s$:ss=asc(s$+chr$(0))
2080 if tt=0 then 2150
2090 print#15,"u1 8 0";tt;ss
2100 nextzz
2110 pp=mm-(xx*8):pp=(pp-1)*32+2
2120 print#15,"b-p 8";pp
2130 print#8,dd$;
2140 print#15,"u2 8 0";tt;ss
2150 close 8:close 15
2160 return
Listing 3. Unterprogramm 2. Schreiben eines Directory-Eintrages
100 rem beispiel fuer eine kleine
101 rem directory-manipulation:
102 rem scratch-schutz einzelner files
103 rem nach anzeige des filenamens:
104 rem j = schuetze dies file
105 rem n = weiter zum naechsten file
106 rem e = ende
107 rem achtung !!! "schuetzt" auch
108 rem schon gescratchte files wenn
109 rem verlangt, stellt sie aber nicht
110 rem wieder her !!!
111 rem scratch-schutz wird im direct.
112 rem durch ein '<' hinter dem
113 rem filetyp angezeigt. naeheres
114 rem siehe tabelle folge 1 !!!
115 rem achtung !!! nur zusammen mit
116 rem den unterprogrammen 1 & 2
117 rem lauffaehig !!!
118 :
119 :
120 mm=0
130 mm=mm+1:dd$="":gosub1000
140 if dd$=nn$thenend
150 printmid$(dd$,4,16):inputaa$
160 if aa$="e"then end
170 if aa$="n"then 130
180 hh$=left$(dd$,1)
190 hh$=chr$(asc(hh$)or2^6)
200 dd$=hh$+right$(dd$,29)
210 gosub2000
220 goto 130
230 end
Listing 4. So kann man Files schützen.
100 rem schreibschutz setzen
101 rem durch aenderung des format-
102 rem kennzeichens in der bam !!!
103 rem funktionsweise :
104 rem formatkennzeichen wird auf
105 rem beliebigen wert ausser 'a'
106 rem gesetzt. ab sofort koennen
107 rem keine schreibvorgaenge ausser
108 rem formatieren durchgefuehrt
109 rem werden. also vorsicht !
110 :
200 open 15,8,15,"i":open8,8,8,"#"
210 print#15,"u1 8 0 18 0"
220 print#15,"b-p 8 2"
230 print#8,"x";
240 print#15,"u2 8 0 18 0"
250 print#15,"i"
260 close8:close15:end
Listing 5. Schützen Sie Ihre Diskette vor jedem Schreibzugriff.
100 rem directory-sorter
101 rem sortiert directory alphabetisch
102 rem bei vielen eintraegen bitte
103 rem etwas geduld (max. 5.min)
104 rem sortiert auch gescratchte files
105 rem mit, stellt sie aber nicht
106 rem wieder her ! sortieralgorithmus
107 rem kann sich in einem solchen fall
108 rem in einer endlosschleife ver-
109 rem heddern. abhilfe: nach 3-4 min.
110 rem stop-taste druecken, dann
111 rem goto 210 eingeben. sind eintr.
112 rem dann noch nicht vollkommen sor-
113 rem tiert, nochmals fuer einige
114 rem minuten laufen lassen.
115 rem achtung !!! nur zusammen mit
116 rem den unterprogrammen 1 & 2
117 rem ablauffaehig !!!
118 :
119 :
120 dimdd$(144)
130 mm=mm+1:gosub1000
140 if dd$=nn$thenmm=mm-1:goto160
150 dd$(mm)=dd$:dd$="":goto130
160 for gg=1tomm-1
170 if mid$(dd$(gg),4,16)<mid$(dd$(gg+1),4,16)then 190
180 hh$=dd$(gg):dd$(gg)=dd$(gg+1):dd$(gg+1)=hh$:ff=1
190 next gg
200 if ff then ff=0:goto160
210 ii=mm
220 formm=1toii:dd$=dd$(mm):gosub2000:nextmm
230 end
Listing 6. Eine einfache Routine, um das Directory zu sortieren.
100 rem beispiel fuer memory-execute
101 rem loest in der floppy langsames
102 rem blinken der roten led (kenn-
103 rem zeichnet normalerweise hard-
104 rem ware-fehler) aus.
105 rem kann nur durch ausloesen eines
106 rem resets entweder durch ein/aus-
107 rem schalten der floppy oder des
108 rem computers beendet werden.
109 rem einsprungsadresse : $ea6e
110 :
120 open15,8,15
130 print#15,"m-e"chr$(110)chr$(234)
140 close 15
150 end
Listing 7. Simulieren Sie einen Hardware-Fehler
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →