| |
CP/M 68K - Arbeiten mit Dateien
Wie der Name schon sagt: die Hauptaufgabe des BDOS (Basic Disc Operation System) ist der Umgang mit Disketten und den Dateien, die darauf gespeichert sind. Dieses Kapitel beschäftigt sich mit den Grundlagen der Verarbeitung von Dateien unter CP/M 68K.
Zurück zum Inhaltsverzeichnis
Themen dieses Kapitels
- Ermitteln des freien Platzes auf einer Diskette
- Ermitteln der Größe einer Datei
- Laden einer Datei in den Speicher
- Zusammensetzen zweier Textdateien
- Löschen und Anlegen von Dateien
Ermitteln des freien Speichers auf einem Laufwerk
Dieses Beispiel zeigt noch nicht direkt den Umgang mit Dateien, ist jedoch geeignet um die Grundlagen Zum Umgang mit dem DMA Buffer zu zeigen. Außerdem kann man das Berechnen des freien Speicherplatzes nutzen, um Fehler beim Speichern von Daten abzufangen.
****************************
* FREE.S
****************************
CURDISK EQU 25 * BDOS Get Current Disk
SETDMA EQU 26 * BDOS Set DMA Address
DISKSPACE EQU 46 * BDOS GET Disk Free Space
PRINTSTR EQU 9 * BDOS Print String
TEXT * ------------------------
START:
MOVE #SETDMA, D0 * BDOS Funktionsnummer
MOVE.L #DMABUF, D1 * Puffer im BSS-Segment
TRAP #2 * DMA Puffer setzen
MOVE #CURDISK, D0 * BDOS Funktionsnummer
TRAP #2 * Aktuelles Laufwerk ermitteln
MOVE D0, D1 * in D1 merken
ADD.B #$41, D0 * ASCII Korrektur
MOVE.L #VAR0, A1 * Ausgabeposition
MOVE.B D0, (A1) * in Ausgabepuffer schreiben
MOVE #DISKSPACE, D0 * BDOS Funktionsnummer
TRAP #2 * Ergebnis im DMA-Puffer
MOVE.L #DMABUF, A1 * Adresse des DMA-Puffers
MOVE.L (A1), D0 * Anzahl freier Blöcke
MOVE.L #VAR1, A0 * Ausgabeadresse im Puffer
BSR PRINTD * als Dezimalzahl
MOVE.L (A1), D0 * Anzahl freier Blöcke
MULU #128, D0 * zu je 128 Bytes
MOVE.L #VAR2, A0 * Ausgabeadresse im Puffer
BSR PRINTD * als Dezimalzahl
MOVE #PRINTSTR, D0 * BDOS Funktionsnummer
MOVE.L #BUFFER, D1 * Start des Textes
TRAP #2 * Ausgeben
RTS * Programmende
DATA * ------------------------
BUFFER: DC.B 13,10
DC.B 'Laufwerk '
VAR0: DC.B ' :',13,10
DC.B '- Freie Sektoren : '
VAR1: DC.B ' ',13,10
DC.B '- Freier Speicher : '
VAR2: DC.B ' ',13,10
DC.B '$'
BSS * ------------------------
DMABUF: DS.B 128 * 128 Byte Puffer für DMA
Ermitteln der Größe einer Datei
Angenommen, wir wollen den Inhalt einer Datei von der Diskette in den Arbeitsspeicher laden. In diesem Fall müssen wir wissen, wie groß die Datei ist und wie viel Arbeitsspeicher (noch) verfügbar ist. Zum Ermitteln der Dateigröße stellt das BDOS eine eigene Funktion (Nummer 35) zur Verfügung. Wir schreiben also zunächst ein Programm mit dem Namen FILESIZE, welches einen Parameter (Name der Datei deren Größe zu ermitteln ist) übernimmt und danach die Größe der angegebenen Datei anzeigt.
****************************
* FILESIZE.S
****************************
OPENFILE EQU 15 * BDOS Open File
CLOSEFILE EQU 16 * BDOS Close File
FILESIZE EQU 35 * BDOS Get File Size
PRINTSTR EQU 9 * BDOS Print String
TEXT
START:
LINK A6, #0 * Stack Frame markieren
MOVE.L 8(A6), A1 * Adresse der Base Page holen
TST.B $80(A1) * Parameter angegeben?
BEQ NOFILE * Nein, dort weiter
LEA $5C(A1), A2 * FCB Adresse nach A2
MOVE #OPENFILE, D0 * BDOS Open File
MOVE.L A2, D1 * FCB Adresse
TRAP #2 * ausführen
CMP #255, D0 * Fehler?
BEQ ERROPEN * Ausgabe und Ende
MOVE #FILESIZE, D0 * BDOS Get File Size
MOVE.L A2, D1 * FCB Adresse
TRAP #2 * ausführen
CLR.L D0 * 24 Bit Wert zusammensetzen
MOVE.B 33(a2), D0 * MSB laden
SWAP D0 * nach oben
MOVE.W 34(a2), D0 * LSB laden
MULU #128, D0 * Mal Sektorgröße
MOVE #CLOSEFILE, D0 * BDOS Close File
MOVE.L A2, D1 * FCB Adresse
TRAP #2 * ausführen
MOVE.L #VAR1, A0 * Ausgabeadresse
BSR PRINTD * Dezimalwert in Buffer
MOVE.L #BUFFER, D1 * Bufferadresse laden
EXIT:
MOVE #PRINTSTR, D0 * BDOS Print String
TRAP #2 * Text ausgeben
UNLK A6 * Stack Frame freigeben
RTS * Programmende
NOFILE:
MOVE.L #ERRNF, D1 * Adresse Fehlermeldung
BRA EXIT * Ausgeben und Ende
ERROPEN:
MOVE.L #ERROP, D1 * Adresse Fehlermeldung
BRA EXIT * Ausgeben und Ende
DATA
BUFFER: DC.B 13,10,'Laenge der Datei in Bytes : '
VAR1: DC.B ' ',13,10
DC.B '$'
ERRNF: DC.B 13,10,'Kein Dateiname angegeben'13,10,'$'
ERROP: DC.B 13,10,'Fehler beim oeffnen der Datei'13,10,'$'
Laden einer Datei in den Speicher
Das folgende Beispiel zeigt, wie man den Inhalt einer beliebigen Datei komplett in den Speicher lädt. Dabei werden die Daten auf der nächsten 128 Byte Grenze unmittelbar hinter das Programm geladen. Dabei werden immer ganze Blöcke zu je 128 Byte aus der Datei geladen.
****************************
* LOADFILE.S
****************************
OPENFILE EQU 15 * BDOS Open File
CLOSEFILE EQU 16 * BDOS Close File
READFILE EQU 20 * BDOS Read File
SETDMA EQU 26 * BDOS Set DMA Address
PRINTSTR EQU 9 * BDOS Print String
TEXT
START:
LINK A6, #0 * Stack Frame markieren
MOVE.L 8(A6), A1 * Adresse der Base Page holen
TST.B $80(A1) * Parameter angegeben?
BEQ NOFILE * Nein, dort weiter
LEA $5C(A1), A2 * FCB Adresse nach A2
MOVE #OPENFILE, D0 * BDOS Open File
MOVE.L A2, D1 * FCB Adresse
TRAP #2 * ausführen
CMP #255, D0 * Fehler?
BEQ ERROPEN * Ausgabe und Ende
MOVE.L #DATEI, D1 * Niedrigste Ladeadresse
AND.L #$FF80, D1 * Anpassung auf naechste
ADD.L #128, D1 * 128 Byte Grenze
MOVE.L #VON, A0 * Startadresse
MOVE.L D1, D0 * ausgeben
BSR PRINT8X
LOOP:
MOVEM.L D1, -(A7) * Ladeadresse merken
MOVE #SETDMA, D0 * DMA Adresse setzen
TRAP #2
MOVE #READFILE, D0 * Lesen aus Datei
MOVE.L A2, D1 * FCB Adresse
TRAP #2
MOVEM.L (A7)+, D1 * Ladeadresse wiederherstellen
ADD.L #128, D1 * nächste Adresse berechnen
TST D0 * Alle Blöcke gelesen?
BEQ LOOP * Nein, dann wiederholen
MOVE #CLOSEFILE, D0 * BDOS Close File
MOVE.L A2, D1 * FCB Adresse
TRAP #2 * ausführen
MOVE.L #OKTXT, D1 * Textausgabe OK
EXIT:
MOVE #PRINTSTR, D0 * BDOS Print String
TRAP #2 * Text ausgeben
UNLK A6 * Stack Frame freigeben
RTS * Programmende
NOFILE:
MOVE.L #ERRNF, D1 * Adresse Fehlermeldung
BRA EXIT * Ausgeben und Ende
ERROPEN:
MOVE.L #ERROP, D1 * Adresse Fehlermeldung
BRA EXIT * Ausgeben und Ende
DATA
OKTXT: DC.B 13,10,'Datei eingelesen von '
VON: DC.B '-------- bis '
BIS: DC.B ‚--------',13,10,'$'
ERRNF: DC.B 13,10,'Kein Dateiname angegeben'13,10,'$'
ERROP: DC.B 13,10,'Fehler beim oeffnen der Datei'13,10,'$'
BSS
DATEI: DS.B 1 * Niedrigste mögliche Ladeadresse
Zusammensetzen zweier Textdateien
Der folgende Code dient dazu, zwei Textdateien zu einer Datei zusammenzuführen. Das Programm erwartet als Parameter zwei Dateinamen von existierenden Textdateien. Beide Dateien werden nacheinander in den Speicher eingelesen und danach wieder auf der Diskette gespeichert. Die zusammengesetzte Textdatei ersetzt die erste Datei. Das bedeutet, dass der Inhalt der zweiten Datei an die erste Datei angehängt wird.
****************************
* JOINTEXT.S
****************************
OPENFILE EQU 15 * BDOS Open File
CLOSEFILE EQU 16 * BDOS Close File
READFILE EQU 20 * BDOS Read File
WRITEFILE EQU 21 * BDOS Write File
SETDMA EQU 26 * BDOS Set DMA Address
PRINTSTR EQU 9 * BDOS Print String
TEXT
START:
LINK A6, #0 * Stack Frame markieren
MOVE.L 8(A6), A1 * Adresse der Base Page holen
LEA $5C(A1), A2 * Adresse FCB1 nach A2
LEA $38(A1), A3 * Adresse FCB2 nach A3
MOVE #OPENFILE, D0 * BDOS Open File
MOVE.L A2, D1 * FCB1 Adresse
TRAP #2 * ausführen
CMP #255, D0 * Fehler?
BEQ ERROPEN * Ausgabe und Ende
MOVE #OPENFILE, D0 * BDOS Open File
MOVE.L A3, D1 * FCB2 Adresse
TRAP #2 * ausführen
CMP #255, D0 * Fehler?
BEQ ERROPEN * Ausgabe und Ende
MOVE.L #DATEI, D1 * Ladeadresse Datei 1
LOOP1:
MOVEM.L D1, -(A7) * Ladeadresse merken
MOVE #SETDMA, D0 * DMA Adresse setzen
TRAP #2
MOVE #READFILE, D0 * Lesen aus Datei
MOVE.L A2, D1 * FCB1
TRAP #2
MOVEM.L (A7)+, D1 * Ladeadresse wiederherstellen
ADD.L #128, D1 * nächste Adresse berechnen
TST D0 * Alle Blöcke gelesen?
BEQ LOOP * Nein, dann wiederholen
MOVE.L #DATEI, A0 * Datei 1 nach Endekennung durchsuchen
LOOP2:
CMP.B #$1A, (A0)+ * Endekennung $1A ?
BNE LOOP2 * bis gefunden
MOVE.L A0, D1 * Ende Datei 1
SUBQ.L #1, D1 * Endekennung überschreiben
LOOP3:
MOVEM.L D1, -(A7) * Ladeadresse merken
MOVE #SETDMA, D0 * DMA Adresse setzen
TRAP #2
MOVE #READFILE, D0 * Lesen aus Datei
MOVE.L A3, D1 * FCB2
TRAP #2
MOVEM.L (A7)+, D1 * Ladeadresse wiederherstellen
ADD.L #128, D1 * nächste Adresse berechnen
TST D0 * Alle Blöcke gelesen?
BEQ LOOP * Nein, dann wiederholen
MOVE #CLOSEFILE, D0 * BDOS Close File
MOVE.L A2, D1 * FCB1
TRAP #2
MOVE #CLOSEFILE, D0 * BDOS Close File
MOVE.L A3, D1 * FCB2
TRAP #2
CLR.B 12(A2) * FCB1 EX = 0
CLR.B 32(A2) * FCB1 CR = 0
MOVE #OPENFILE, D0 * BDOS Open File
MOVE.L A2, D1 * FCB1
TRAP #2
CMP #255, D0 * OK?
BEQ ERROPEN
MOVE.L #DATEI, D1 * Startadresse
LOOP4:
MOVEM.L D1, -(A7) * Adresse merken
MOVE #SETDMA, D0 * BDOS Set DMA Address
TRAP #2
MOVE #WRITEFILE, D0 * BDOS Write File
MOVE.L A2,D1 * FCB1
TRAP #2
MOVEM.L (A7)+, D1 * Adresse wiederherstellen
TST D0 * Fehler?
BNE ERRWRITE
MOVE.L D1, A0 * Aktuellen Block absuchen
MOVE #127, D3 * 128 Bytes
LOOP5:
CMP.B #$1A, (A0)+ * Endekennung enthalten?
BEQ FERTIG
DBRA D3, LOOP5
ADD.L #128, D1 * Nächster Block
BRA LOOP4
FERTIG:
MOVE #CLOSEFILE, D0 * BDOS Close File
MOVE.L A2, D1 * FCB1
TRAP #2
MOVE.L #OKTXT, D1 * Textausgabe OK
EXIT:
MOVE #PRINTSTR, D0 * BDOS Print String
TRAP #2 * Text ausgeben
UNLK A6 * Stack Frame freigeben
RTS * Programmende
ERROPEN:
MOVE.L #ERROP, D1 * Adresse Fehlermeldung
BRA EXIT * Ausgeben und Ende
ERRWRITE:
MOVE.L #ERRWR, D1
BRA EXIT
DATA
OKTXT: DC.B 13,10,'Dateien erfolgreich zusammengesetzt',13,10,'$'
ERROP: DC.B 13,10,'Fehler beim Laden einer Datei',13,10,'$'
ERRWR: DC.B 13,10,'Fehler beim Schreiben der Datei',13,10,'$'
BSS
DATEI: DS.B 1 * Niedrigste mögliche Ladeadresse
Löschen und Anlegen von Dateien
Zum Abschluss des Kapitels ein kleines Programm zum Anlegen einer neuen Textdatei auf der Diskette. Das Beispiel ist absichtlich kurz gehalten und soll nur dazu dienen, die Arbeitsweise darzustellen. Beim Ausprobieren bitte darauf achten, dass eine bereits vorhandene Datei mit dem angegebenen Dateinamen überschrieben wird.
****************************
* MAKETEXT.S
****************************
OPENFILE EQU 15 * BDOS Open File
CLOSEFILE EQU 16 * BDOS Close File
WRITEFILE EQU 21 * BDOS Write File
MAKEFILE EQU 22 * BDOS Make File
SETDMA EQU 26 * BDOS Set DMA Address
PRINTSTR EQU 9 * BDOS Print String
TEXT
START:
LINK A6, #0 * Stack Frame markieren
MOVE.L 8(A6), A1 * Adresse der Base Page holen
TST.B $80(A1) * Parameter vorhanden?
BEQ NOFILE * Fehlermeldung ausgeben
LEA $5C(A1), A2 * Adresse FCB1 nach A2
MOVE #OPENFILE, D0 * BDOS Open File
MOVE.L A2, D1 * FCB1 Adresse
TRAP #2 * Testen ob Datei schon vorhanden
CMP #255, D0 * Fehler?
BEQ CONT * Nicht vorhanden, anlegen
MOVE #DELETEFILE, D0 * BDOS Delete File
MOVE.L A2, D1 * FCB1
TRAP #2
CONT:
MOVE.L #MAKEFILE, D0 * BDOS Make File
MOVE.L A2, D1 * FCB1
TRAP #2
CMP #255, D0 * Fehler?
BEQ ERRMAKE
MOVE #OPENFILE, D0 * BDOS Open File
MOVE.L A2, D1 * FCB1
TRAP #2
MOVE.L #INHALT, D1 * Zu schreibende Daten
MOVE #SETDMA, D0 * BDOS Set DMA Address
MOVE.L #INHALT, D1 * Startadresse
TRAP #2
MOVE #WRITEFILE, D0 * BDOS Write File
MOVE.L A2,D1 * FCB1
TRAP #2
TST D0 * Fehler?
BNE ERRWRITE
MOVE #CLOSEFILE, D0 * BDOS Close File
MOVE.L A2, D1 * FCB1
TRAP #2
MOVE.L #OKTXT, D1 * Textausgabe OK
EXIT:
MOVE #PRINTSTR, D0 * BDOS Print String
TRAP #2 * Text ausgeben
UNLK A6 * Stack Frame freigeben
RTS * Programmende
NOFILE:
MOVE.L #ERRNO, D1 * Adresse Fehlermeldung
BRA EXIT * Ausgeben und Ende
ERRMAKE:
MOVE.L #ERRMA, D1 * Adresse Fehlermeldung
BRA EXIT * Ausgeben und Ende
ERRWRITE:
MOVE.L #ERRWR, D1 * Adresse Fehlermeldung
BRA EXIT * Ausgeben und Ende
DATA
OKTXT: DC.B 13,10,'Datei erfolgreich erstellt',13,10,'$'
ERRNO: DC.B 13,10,'Fehler kein Dateiname angegeben',13,10,'$'
ERRMA: DC.B 13,10,'Fehler beim Anlegen der Datei',13,10,'$'
ERRWR: DC.B 13,10,'Fehler beim Schreiben der Datei',13,10,'$'
INHALT: DC.B '*********************************',13,10
DC.B '* NEU ANGELEGTE DATEI',13,10
DC.B '*********************************',13,10
DC.B $1A
Fazit
Auch wenn die Beispiele immer länger werden, so schwierig ist die Nutzung der BDOS-Funktionen nicht. Viel wichtiger ist es, sich vorher ein Konzept für ein umzusetzendes Programm zu erstellen.
Weiter zu Teil 8 der Serie: Bibliotheken
Zurück zu Teil 6 der Serie: Wichtige Datenstrukturen
|