![]() |
![]() |
Startseite News   NDR-NKC ![]() ![]() ![]() NKC Emulator Z80 Section ![]() ![]() ![]() 68000 Section ![]() ![]() ![]() ![]() ![]() 8088 Section ![]() ![]() Bussysteme Stromversorgung Input / Output Grafikkarten Speicherkarten Massenspeicher Weitere Baugruppen Projekte Dokumentation Datenblätter Glossar Portraits Links Impressum |
CP/M 68K Programmierkurs - Arbeiten mit DateienWie 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.Themen dieses Kapitels
Ermitteln des freien Speichers auf einem LaufwerkDieses 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 DateiAngenommen, 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 SpeicherDas 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 TextdateienDer 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 DateienZum 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 FazitAuch 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.
|