Klaus Kämpf: CP/M 2.2 Assembler-Listing
ISBN 3-925074-II-2
1. Auflage, Dezember 1985
© 1985 by Röckrath MICROCOMPUTER
Noppiusstr. 19
5100 Aachen
Das Betriebsystem CP/M ist seit Jahren das Standard-Betriebsystem
für 8080- und Z80-Mikrocomputer. Viele derzeit erhältliche
Bücher befassen sich ausführlich mit der Bedienung des
CP/M und der Nutzung der verschiedenen Betriebssystem-Funktionen.
Das vorliegende Buch bietet nun erstmals einen Einblick in
die inneren Abläufe des CP/M 2.2 und beschreibt ausführlich
die Arbeitsweise dieses Betriebsystems. Neben einer Beschreibung
der internen Datenformate und der Diskettenparameter
wird jede BDOS-Funktion in ihrem Ablauf dokumentiert. Daran
schließen sich die kommentierten Source-Listings der beiden
CP/M-Teile CCP und BDOS an. für diejenigen Anwender, die sich
ein CP/M-BIOS selber schreiben wollen, werden noch Tips und
Tricks zur Verbesserung des CP/M 2.2 gegeben.
Aachen, im November 1985
Klaus Kämpf
Die Geschichte des Betriebsystems CP/M ist eng verknüpft mit der Entwicklung der Mikroprozessoren und Mikrocomputer. Die folgende Einleitung soll daher einen kurzen Rückblick auf die Entstehung und weitere Entwicklung des CP/M geben:
Im Herbst 1973 kündigte die amerikanische Elektronikfirma
Intel einen Mikroprozessor mit der Bezeichnung '8080' als
Nachfolger ihres Prozessors '8008' an.
Der 8080 war damals der erste Mikroprozessor, der nicht nur
diskrete Logik ersetzte, sondern auch zum Einsatz als Zentraleinheit
(CPU) für Mikrocomputer geeignet war. Im April
1974 kamen dann die ersten Exemplare des 8080 zu einem Preis
von etwa 360 Dollar auf den Markt.
Einer der ersten Mikrocomputer mit dem 8080 als Zentraleinheit
war der 'Altair 8800'.
Der Altair 8800 wurde im Januar 1975 als Bausatz von der
Zeitschrift 'Popular Electronics' vorgestellt. Inclusive
Prozessor, Netzteil, Hauptplatine, binärer Ein- und Ausgabe
und einem Speicher von 256 Bytes (!) kostete dieser Bausatz
395 Dollar (damals ca. 1500 DM).
Der Altair 8800 war aus mehreren Einzelplatinen aufgebaut,
die alle auf einer gemeinsamen Busplatine steckten. Ein
größer Vorteil dieses Aufbaus war, das auch Zusatzplatinen
anderer Firmen betrieben werden konnten.
'Digital Microsystems' war die erste Firma, die einen 'Disk-
Controller' zum Anschluss von 8 Zoll Diskettenlaufwerken an
den Altair 8800 anbot und auch ein Betriebssystem dazu lieferte.
Unter der Bezeichnung 'Control Program for Microcomputer',
kurz 'CP/M', wurde dieses Betriebssystem auch getrennt
verkauft und entwickelte sich rasch zu einem Standard-
Betriebssystem für 8080-Mikrocomputer.
Das erste CP/M (Versionsnummer 1.3, später 1.4) war auf folgende Grundkonfiguration abgestimmt:
Gedacht war ein solches System vor allem zur Entwicklung von Programmen für den 8080 Mikroprozessor. Noch heute zeugen die von Digital Research mitgelieferten Programme ED, ASM oder DDT davon.
Um die Größe des Betriebssystems möglichst klein zu halten, wurde das CP/M in drei verschiedene Teile aufgespalten:
Der CCP bildet die Benutzerebene des Betriebssystems, über
die der Anwender Befehle eingeben und Programme starten kann.
Da nach dem Start eines Programms die Benutzerebene überflüssig
ist, kann der vom CCP eingenommene Speicherplatz vom
jeweils laufenden Programm mitbenutzt werden.
Der CCP ist ein in sich abgeschlossenes Programm, das, wie
normale CP/M-Programme auch, Funktionen des BDOS benutzt.
Das BDOS ist der eigentliche Betriebssystem-Kern und auf allen CP/M Rechnern identisch. Dadurch ist die Kompatibilitat zwischen allen Rechnern die CP/M verwenden garantiert.
Das BIOS bildet die 'Schnittstelle' zwischen dem BDOS und der Hardware des Computers.
Notwendig für Anwenderprogramme sind nur die beiden Teile 'BDOS' und 'BIOS'. Sie werden zusammen auch als 'FDOS' bezeichnet.
Damit das CP/M in verschiedenen Speichergrößen ablaufen kann, ist der Speicherbereich, in dem das CP/M liegt, nicht festgelegt. Statt dessen ist die erste Speicherseite (256 Bytes) für Systeminformationen reserviert und beinhaltet auch den 'Bezugspunkt' zum CP/M in Form eines Sprungbefehls.
Ab der zweiten Seite beginnt der Speicherbereich für Anwenderprogramme, die sogenannte 'Transient Program Area', kurz TPA. Die TPA reicht bis zur ersten Adresse des CP/M, das immer am oberen Speicherende liegt.
Wichtig für den Betrieb von CP/M ist, daß der Speicher durchgehend ist und bei der Adresse 0000H beginnt. Da Anwenderprogramme immer ab einer fester Adresse arbeiten, ist dadurch eine einheitliche Startadresse der TPA festgelegt, was erst einen Programmaustausch zwischen CP/M-Rechnern ermöglicht.
Die Speicheraufteilung im CP/M sieht im Überblick so aus:
An der Adresse BOOT befindet sich grundsätzlich ein Sprung
zur Warmstartroutine des BIOS. Diese Routine lädt nach Beendigung
eines Programms den CCP und das BDOS neu in den
Speicher und startet danach wieder den CCP. Das Sprungziel
ist immer der zweite Eintrag in der BIOS-Sprungtabelle, also
BIOS + 0003H.
Daraus kann ein Programm auch die Startadresse des BIOS
berechnen und, falls es das BDOS nicht braucht, auch den vom
BDOS belegten Speicherbereich nutzen.
Läßt ein Programm den Speicherplatz über CBASE unberührt, so kann es auch durch ein einfaches 'RET' die Kontrolle wieder zurück an den CCP geben.
An der Adresse BOOT + 5 (normalerweise 0005H) steht ein
Sprung nach FBASE, der die Verbindung zwischen Programmen und
dem FDOS herstellt. Auch der CCP benutzt diesen Sprungbefehl
bei der Anforderung von FDOS-Funktionen.
Dieses Sprungziel kann aber durch gewisse Programme (z.B.
DDT) verändert werden.
Im normalen CP/M-Gebrauch ist die Zieladresse dieses Sprunges der niedrigste, vom FDOS verwendete Speicherplatz, Rechnet man den Speicherplatz des CCP mit zur TPA, so ist diese Adresse genau die höchste TPA-Adresse +1.
Das DDT-Programm setzt dies insofern voraus, als das es sich selbst 'unter' das FDOS legt und den Sprung nach FBASE auf sich selbst legt. Startet man im DDT ein Programm, so ist der DDT geschützt, solange das Programm die Sprungadresse als obere Speichergrenze benutzt. Außerdem laufen im Trace-Modus des DDT alle BDOS-Aufrufe über den DDT, der damit die Kontrolle über das System behält.
Das CP/M ist als single-user, single-tasking Betriebssystem ausgelegt. Das heißt, daß das CP/M zu einer Zeit nur einen Benutzer und ein Programm bearbeiten kann und damit auch immer nur ein Laufwerk und eine Datei (File) 'kennt'.
Jedes Laufwerk muß daher vor der Bearbeitung beim BDOS angemeldet werden, das sich daraufhin auf dieses Laufwerk einstellt. Die zu einem Laufwerk gehörenden Daten und Tabellen sind im BIOS gespeichert, daß sie auf Anfrage dem BDOS zur Verfügung stellt.
Das Anmelden dient dem BDOS zur Einstellung seiner internen Parameter auf das neue Laufwerk bzw. auf die im Laufwerk befindliche Diskette. über verschiedene BDOS-Funktionen kann die Diskette dann gelesen und geschrieben werden.
Zum Schreiben muß dem BDOS aber bekannt sein, welche Teile der Diskette bereits Daten enthalten und welche noch frei sind. Aus diesem Grund wird bei der Laufwerks-Anmeldung eine Belegungstabelle der Diskette erstellt, die Auskunft über freie und belegte Teile gibt.
Zur Speicherung neuer Daten kann das BDOS dann die benötigten
Informationen dieser Tabelle entnehmen.
Da sich das BDOS noch zusätzlich 'merkt', ob ein Laufwerk
schonmal angemeldet wurde oder nicht, braucht die Belegungstabelle
nur dann erstellt zu werden, wenn das Laufwerk zum
ersten Mal angewählt wird.
Das BDOS beschreibt eine Diskette immer anhand der vorliegenden
Belegungstabeile, was bei einem unkontrollierten Diskettenwechsel
fatale Folgen haben kann.
Zur Umgehung dieses Problems verfügt das CP/M über den sogenannten
Warmstart.
Durch einen Warmstart wird das BDOS neu geladen und dadurch sein 'Gedächtnis' der bekannten Laufwerk gelöscht. Bei jeder folgenden Laufwerksanwahl wird dadurch die Belegungstabelle jeweils neu erstellt.
Zum Diskettenwechsel ohne Warmstart bietet das BDOS auch die Möglichkeit, einzelne Laufwerke ab- und neu wieder anzumelden. Der Warmstart nach einem Diskettenwechsel ist immer Aufgabe des Benutzers; wenn er den Warmstart vergisst, tritt das Problem wieder auf.
Da Datensicherheit in einem Betriebssystem nunmal das Wichtigste ist, ist im CP/M noch ein zweiter Schutzmechanismus eingebaut, die Prüftabelle.
Bei der Anmeldung eines Laufwerks wird, neben der Belegungstabelle,
auch eine Prüfsumme über das Inhaltsverzeichnis der
Diskette erstellt und gespeichert.
Vor jeder Schreiboperation bildet das BDOS diese Prüfsumme
neu und vergleicht sie mit der zuletzt für dieses Laufwerk
errechneten Prüfsumme.
Anhand der Differenz dieser beiden Summen erkennt das BDOS
einen Diskettenwechsel und sperrt jeden weiteren Schreibzugriff
auf das Laufwerk.
Aus diesem Grund müssen im CP/M Diskettenwechsel dem System immer ausdrücklich mitgeteilt werden. Das Anmelden einer Diskette wird auch als 'einloggen' (engl. Log in) und das Abmelden als 'ausloggen' (engl. Log out) bezeichnet.
Track/Spur DPB-Wert (Disk Parameter Block) +-----------------------------------+ 0 | Systemspur 0 | a = OFF Systemspuren 0..OFF-1 | ... | a-1 | Systemspur a-1 | +-----------------------------------+ a | Block 0 | Block 1 | ... | n Blöcke | | DRM+1 Einträge a 32 Byte | Directory | | | -> n = (DRM+1)*32/BLS (aufrunden) | | Block n-1 | -> b = (DRM+1)/4/SPT + a (aufrunden) +-----------------------------------+ b | Block n | Block n+1 | ... | m-n Blöcke | | | | Blockgröße 1K .. 16KByte | | (s. BSH und BLM) | | BLS = 128 * 2^BSH = 128 * (BLM+1) | Dateien | | | Block n muss nicht am Spuranfang | | liegen, ist aber fast immer so! | | | | | | | | | | | | | | | | m = DSM-1 | | Block m ist nicht immer vollst. | | auf der Disk enthalten trk-1 | | Block m-1 | Block m | +-----------------------------------+
Jede Diskette ist physikalisch in Spuren (engl. Tracks) und
Sektoren (engl. Sectors) aufgeteilt.
Der Datentransfer von und zu der Diskette spielt sich immer
in ganzen Sektoren ab. Aufgabe des Programms ist es, den
Sektorinhalt zu interpretieren und die einzelnen Bytes auszulesen.
Zur Vereinfachung von Diskettenoperationen werden im CP/M - wie in anderen Betriebssystemen auch - zusammenhängende Informationen in Dateien (engl. Files) zusammengefasst.
Jede Datei hat einen Dateinamen (engl. Filename) und kann unter diesem Namen bearbeitet werden. Die Ansteuerung einzelner Spuren und Sektoren auf der Diskette wird vom Betriebssystem übernommen.
Dateinamen bestehen im CP/M aus bis zu 8 Zeichen, gefolgt von bis zu 3 Zeichen zur Kennzeichnung eines Dateityps (engl. Filetype). Filename und Filetyp werden meist auch zusammen als Filename bezeichnet.
Die Information, welche Daten bzw. welche Files auf einer Diskette aufgezeichnet sind, ist am Anfang der Diskette im Inhaltsverzeichnis (engl. Directory) enthalten.
In der Directory stehen alle wichtigen Daten, die das BDOS zur Bearbeitung der Diskette benötigt. für jedes File sind dies:
Fordert ein Programm bestimmte Daten unter Angabe eines Filenamens an, so kann das BDOS aus den Directory-Informationen den exakten Sektor auf der Diskette berechnen.
Das BDOS teilt jede Diskette in Blöcke (engl. Blocks) auf, um damit den Verwaltungs- und Speicheraufwand für die Belegungstabelle zu verkleinern.
Während das CP/M 1.4 noch eine feste Blocklänge von 1 Kilobyte hatte, ist die Länge eines Blocks im CP/M 2.2 variabel gehalten.
Da die Belegungstabelle in Blöcken geführt wird, kann das BDOS Diskettenplatz auch nur blockweise vergeben. Nachteil dieser Aufteilung ist, das ein File immer ganze Blöcke belegt, auch wenn die tatsächliche Filelänge kleiner ist.
Das CP/M 1.4 baut auf der physikalischen Sektorlänge des IBM
3740 Formates (128 Bytes pro Sektor) auf.
Alle Dateioperationen geschehen im CP/M 1.4 in 128 Byte
'Portionen' und auch die Länge eine Files wird in Vielfachen
von 128 Bytes gemessen.
CP/M 2.2 hat diese Rechenweise für Files übernommen, unterscheidet
aber zwischen Sektoren auf der Diskette und File-
'Portionen'.
Ein Sektor ist im CP/M 2.2 die kleinste physikalische Aufzeichnungseinheit
auf der Diskette. Eine Datei-'Portion' wird
im CP/M 2.2 als Record bezeichnet. Ein Record ist der
kleinste Teil einer Datei, den CP/M noch addressieren bzw.
unterscheiden kann.
Die interne Bearbeitung von Disketten geschieht im CP/M 2.2 immer in einzelnen Records. Der Name 'Record' wird daher im weiteren nicht nur in Verbindung mit Files, sondern auch allgemein für Diskettendaten benutzt.
Im Zusammenhang mit Disketten ist auch die Bezeichnung 'logischer Sektor' für einen Record üblich. Damit wird vor allem der Unterschied zwischen einem Sektor auf der Diskette ('physikalischer Sektor') und einem 'Sektor', wie ihn das BDOS verarbeitet, deutlich gemacht.
Obwohl das BIOS eigentlich den physikalischen Teil des CP/M
bildet, geschieht der Datentransfer zwischen BDOS und BIOS in
logischen Sektoren.
Zum einen wird, z.B. beim Laden einer Datei in den Speicher,
am BDOS 'vorbei' geladen. Das heißt, daß das BDOS dem BIOS
nur mitteilt, wohin der nächste logische Sektor geladen werden
soll, und den Rest dem BIOS überlässt.
Der zweite Grund ist, daß das neue CP/M 2.2 nach der Einführung
moglichst schnell Verbreitung finden sollte. Dazu
musste der Aufwand zur Umstellung eines CP/M 1.4 BIOS auf die
CP/M 2.2 Version klein gehalten werden. Da das CP/M 1.4 nur
mit dem IBM 3740 Diskettenformat arbeitet, können die Diskettenein-
und ausgaberoutinen vom CP/M 1.4 BIOS zum CP/M 2.2
BIOS übernommen werden.
Im CP/M 2.2 hat das BIOS die Aufgabe, zwischen physikalischen
und logischen Sektoren zu trennen.
Der bei einer physikalischen Sektorlänge von mehr als 128
Bytes notwendige Aufwand ist nicht ganz unerheblich.
Das BIOS muß beim Lesen jeden physikalischen Sektor in logische
Sektoren aufspalten und beim Schreiben logische Sektoren
zu einem physikalischen Sektor zusammenfassen.
CP/M 2.2 unterstützt dieses Zusammenfassen und Aufspalten (engl. Blocking and Deblocking) durch einen weiteren Parameter, der den Lese/Schreibroutinen im BIOS übergeben wird.
Die Directory enthält alle Informationen über die auf der Diskette gespeicherten Files. Dazu gehören neben dem Filenamen und Filetyp die Länge des Files und die von ihm belegten Blöcke.
Jedes File benutzt mindestens einen Eintrag (engl. Entry)
innerhalb der Directory. Die Länge eines Eintrags ist im CP/M
auf 32 Bytes festgelegt. Damit passen in jeden Directory-
Record genau 4 Einträge.
Directory-Funktionen im BDOS geben daher meist einen Directory-
Code zurück, der die relative Nummer eines Eintrages im
Directory-Record angibt. über diese Nummer können Programme
einen Eintrag in der Directory 'finden' und selbst bearbeiten.
Als Directory-Bereich auf der Diskette ist im CP/M 1.4 der
erste Block reserviert. Damit beträgt die Höchstzahl an Einträgen
auf einer CP/M 1.4 Diskette 64. Im CP/M 2.2 ist die
Größe der Directory in gewissen Grenzen frei wählbar.
Es können bis zu 16 Blöcke als Directory reserviert werden
und auch die Anzahl der Einträge ist ein getrennter Parameter.
Bei der maximalen Blockgröße von 16 kbyte sind im
CP/M 2.2 maximal 16384 8192 Directory-Einträge möglich.
Zur besseren Handhabung größerer Directories gibt es im CP/M 2.2 sogenannte User-Bereiche (engl. User Areas).
Jeder Directory-Eintrag enthält eine zusätzliche Kennung, die Usernummer (engl. User Number).
Das BDOS arbeitet immer nur innerhalb eines Userbereichs und
erkennt nur die Directory-Einträge, die innerhalb des aktuellen
Userbereichs liegen, d.h. die entsprechende Usernummer
haben.
Eine Usernummer kann daher nicht einzelnen Files zugewiesen
werden, sondern immer nur dem BDOS als ganzem.
User-Bereiche können vom CCP aus mit dem 'USER'-Befehl angewählt werden. Das BDOS unterscheidet zwar bis zu 32 User- Bereiche, der CCP erlaubt jedoch nur die Anwahl der ersten 16.
Zum Arbeiten mit einem File benötigt das BDOS alle Informationen
des zum File gehörenden Directory-Eintrags.
Zu diesem Zweck muß ein Programm, will es mit einem File
arbeiten, dieses File erst eröffnen (engl. open).
Dazu stellt das Programm dem BDOS einen 32 Byte großen Speicherbereich - den Datei Kontroll Block (engl. File Control Block, FCB) - zur Verfügung.
Durch diese Speicherung der Directory-Informationen in einem
getrennten Bereich werden zwei Ziele erreicht:
Erstens wird die Anzahl der Directory-Zugriffe erheblich
reduziert, da das BDOS die Daten des Directory-Eintrags immer
dem FCB entnimmt.
Zweitens können dadurch, im Widerspruch zur 'Ein-Benutzer-
Struktur' des BDOS, mehrere Files quasi-gleichzeitig bearbeitet
werden.
Bei jeder Fileoperation wird dem BDOS die Adresse des jeweiligen
FCB übergeben. Das BDOS entnimmt daraufhin die wichtigsten
Daten direkt dem FCB und speichert sie intern. Dadurch
wird - aus der Sicht einer BDOS-Funktion - immer nur
ein File zu einer Zeit bearbeitet.
Nach Abschluß der Fileoperation schreibt das BDOS die Daten
zurück in den FCB, der damit immer die aktuellen Daten enthält.
Ist die Bearbeitung eines Files beendet, so wird es wieder
geschlossen (engl. close).
Beim Schließen eines Files schreibt das BDOS die Informationen
des FCB wieder zurück in den Eintrag.
Dieses Zurückschreiben ist aber nur dann wichtig, wenn die
Informationen des Eintrags (bzw. FCB) wirklich geändert wurden.
Im CP/M kann nur die Schreibfunktion die Größe eines
Files und damit die Daten des FCB beeinflussen.
BDOS-intern erhält daher jeder FCB eine getrennte Kennung,
die Auskunft darüber gibt, ob eine Schreiboperation auf
diesem FCB ausgeführt wurde oder nicht.
Nach dem Öffnen wird diese Kennung auf 'nicht geschrieben'
bzw. 'nicht geändert' (engl. not altered) gesetzt und bei
einer Schreiboperation gelöscht.
Die BDOS-Funktion 'File schließen' aktualisiert einen Eintrag
nur, wenn diese Kennung gelöscht ist.
Im CP/M 1.4 kann eine Diskette bis zu 256 Blöcken, bei 1k Blockgröße entsprechend 256 kbytes, umfassen. Blocknummern werden im CP/M 1.4 immer als 8-Bit Werte verwaltet.
Von den 32 Bytes eines Eintrags sind 16 Bytes für die Speicherung der vom File belegten Blocknummern vorgesehen. Pro Eintrag können damit im CP/M 1.4 maximal 16 Blöcke adressiert werden, was einer Filegröße von 16 kbytes pro Eintrag entspricht. für jeweils 16k Daten ist daher im CP/M 1.4 ein eigener Directory-Eintrag nötig.
In Records ausgedrückt entspricht die maximale Filegröße pro
Eintrag bzw. FCB 128 Records (128 * 128 Bytes = 16k Bytes).
Da Recordnummern im CP/M immer relativ gezählt werden, ist
der Bereich der Recordnummern - bezogen auf den Eintrag - 0
bis 127. Bei Erreichen der Recordnummer 128 wird im CP/M 1.4
automatisch der nächste Eintrag aus der Directory gelesen und
die Nummerierung der Records wieder bei 0 angefangen.
Jeder zu einem File gehörende Eintrag wird daher noch mit
einer Eintragsnummer versehen.
Zur Anwahl eines bestimmten Records innerhalb eines Files
ist also sowohl die Record- als auch die Eintragsnummer anzugeben.
Die maximale Anzahl von Eintragen pro File ist im CP/M 1.4
auf 16 begrenzt, sodas ein File höchstens eine Größe von 256
kbytes erreichen kann.
Diese Zahlweise der Eintrags- und Recordnummern wurde beim Übergang von CP/M 1.4 zu CP/M 2.2 aus Kompatibilitatsgründen beibehalten.
Da das CP/M 2.2 aber mit verschiedenen Blockgrößen arbeiten
kann, trifft die Bezeichnung 'Eintragsnummer' nicht mehr zu.
Das CP/M 2.2 trennt aus diesem Grund zwischen den Begriffen
Extend und Eintrag.
Ein Extend im CP/M 2.2 entspricht dem Adressierungsbereich
eines Eintrags im CP/M 1.4 - 16 kbyte.
Ein Eintrag im CP/M 2.2 dagegen kann, bei der maximalen
Blockgröße von 16 kbytes, bis zu 16 Extends enthalten.
Intern werden Files im CP/M 2.2 grundsätzlich in Extends verwaltet, um so die Zahlweise der Recordnummern von 0 bis 127 zu erhalten.
1 Extend = 128 Records = 16 kByte
Das CP/M 2.2 fasst noch zusätzlich jeweils 32 Extends zu
einer Extendgruppe (engl. Extend Group) zusammen.
Ein File kann aus bis zu 16 Extendgruppen aufgebaut sein, was
die maximale Länge eines Files auf 65536 Records (8 Megabyte)
begrenzt.
Die laufende Recordnummer eines Files wird BDOS-intern immer in den drei Teilen Extendgruppe, Extend und Record verwaltet.
Ein Eintrag umfasst 32 Bytes und enthält alle Informationen, die das BDOS zur Lokalisierung der Daten auf der Diskette benötigt. Das folgende Schema soll den prinzipiellen Aufbau eines Eintrages im CP/M 2.2 verdeutlichen:
+-------------------------------------------------+ : UN N1 N2 N3 N4 N5 N6 N7 N8 T1 T2 T3 EX S1 EG RC : +-------------------------------------------------+ Pos. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +-------------------------------------------------+ : B0 . . . . . . . . . . . . . . Bn : +-------------------------------------------------+ Pos. 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 mit UN Usernummer des Files (0..31) N1...N8 Filename (8 Zeichen) T1...T3 Filetyp (3 Zeichen) und Fileattribut EX Höchste Extendnummer des Eintrags (0..31) S1 unbenutzt, immer 0 EG Höchste Extendgruppe des Eintrags (0..15) (auch als S2 bezeichnet) RC Anzahl der Records im Extend EX (0..127) B1...Bn Nummern der belegten Blöcke (Blocktabelle)
Die erste Position des Eintrags enthält die Nummer des Userbereiches zu dem das File gehört. Der Wert E5H an dieser Stelle weist den Eintrag als unbelegt aus.
Die Positionen N1 bis N8 bzw. T1 bis T3 sind Filename und Filetyp des zum Eintrag gehörenden Files in Großschrift.
Umfasst ein Filenamen weniger als 8 Zeichen, so werden die nicht benutzten Stellen mit Leerzeichen aufgefüllt. Gleiches gilt auch für den Filetyp.
Da Filenamen und Filetyp ASCII-Wert sind, werden immer nur
die unteren 7 der 8 Bits an den Positionen N1 bis N8 und T1
bis T3 ausgenutzt. Die höchsten Bits an den Positionen T1 bis
T3 werden zur Kennzeichnung eines Fileattributes verwendet.
CP/M 2.2 nutzt von den drei möglichen Attribut-Bits aber nur
T1 und T2 für die Attribute 'Schreibgeschützt' und 'System-
file' aus. Das dritte Bit kann von Anwenderprogrammen
für eigene Zwecke genutzt werden.
Bit 7 der Position T1 weist ein File als 'schreibgeschützt'
aus. Vor jedem Schreibzugriff wird dieses Bit getestet, und,
falls es auf '1' steht, der Zugriff mit der Fehlermeldung
'FILE R/O' abgebrochen.
Bit 7 der Position T2 zeigt das Attribut 'Systemfile' an.
Dieses Attribut wird jedoch nicht vom BDOS, sondern nur vom
'DIR'-Befehl im CCP beachtet.
EX enthält die Extendnummer, EG die Extendgruppe des letzten durch den Eintrag abgedeckten Record. EX und EG werden, bei mehreren Eintragen zu einem File, immer relativ zum Fileanfang gerechnet.
RC ist die Anzahl von Records im höchsten Extend (EX) des
Eintrages. RC liegt normalerweise im Bereich zwischen 0 und
127.
Ein Wert von 128 in RC zeigt an, das auch der letzte Extend
mit 128 Records gefüllt ist. In diesem Fall folgt noch ein
weiterer Eintrag (Folgeeintrag).
In der Blocktabelle stehen die vom File belegten Blocknummern.
Die Blocktabelle kann bei 8-Bit Blocknummern bis zu 16 Blöcke
und bei 16-Bit Blocknummern bis zu 8 Blöcke umfassen.
Der Aufbau eines File Control Blocks entspricht dem eines
Directory-Eintrags.
Vor dem Öffnen eines Files enthält der FCB nur das Laufwerk,
den Filename und den Filetyp des gewünschten Files. Zusätzlich
kann noch eine Extendnummer angegeben werden, so daß ein
bestimmter Extend schon beim Öffnen erreicht wird.
Die Anwahl einer Extendgruppe ist nicht direkt möglich; geöffnet wird immer die erste Extendgruppe.
Zum Öffnen muß der FCB folgende Daten enthalten:
+------------------------------------------ ------+ : LW N1 N2 N3 N4 N5 N6 N7 N8 T1 T2 T3 EX 0 ... 0 0 : +------------------------------------------ ------+ Pos. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 31 32 mit LW Laufwerkscode 0 - Aktuelles Laufwerk 1 - Laufwerk A 2 - Laufwerk B ... 16 - Laufwerk P N1...N8 Filename (8 Zeichen) T1...T3 Filetyp (3 Zeichen) EX Extendnummer
Die 'File Öffnen'-Funktion im BDOS durchsucht die Directory des gewünschten Laufwerks nach einem passenden Eintrag und kopiert diesen in den FCB. Alle weiteren Filefunktionen des BDOS stützen sich nur noch auf die im FCB enthaltenen Informationen.
Ein geöffneter FCB bezieht sich immer auf einen bestimmten Extend des Files. Die genaue Recordnummer innerhalb dieses Extends wird in einem weiteren Byte an der Position 32 gespeichert. Durch Vergleich dieser Recordnummer mit der höchsten Recordnummer des Extends kann das BDOS entscheiden, wann das Ende eines Extends erreicht ist. Die genaue Belegung der 33 Bytes eines geöffneten FCB gibt das folgende Schema:
FCB nach dem Öffnen:
+-------------------------------------------------+ : LW N1 N2 N3 N4 N5 N6 N7 N8 T1 T2 T3 EX S1 EG RC : +-------------------------------------------------+ Pos. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +----------------------------------------------------+ : B0 . . . . . . . . . . . . . . Bn CR : +----------------------------------------------------+ Pos. 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 mit LW Nummer des Laufwerks 0 - Aktuelles Laufwerk 1 - Laufwerk A 2 - Laufwerk B ... 16 - Laufwerk P N1...N8 Filename (8 Zeichen) T1...T3 Filetyp (3 Zeichen) EX Aktuelle Extendnummer (0..31) S1 unbenutzt, immer 0 EG Aktuelle Extendgruppe (0..15) RC Anzahl der Records im Extend EX (0..127) B1...Bn Nummern der belegten Blöcke (Blocktabelle) CR Aktuelle Recordnummer im Extend EX (0..127)
Über die Position LW können vom BDOS auch nach dem Öffnen noch Files von verschiedenen Laufwerken unterschieden werden.
Ist LW nicht 0, so wird vor jeder Fileoperation das gewünschte
Laufwerk angewählt und nach Abschluss der Operation
wieder auf das alte Laufwerk zurückgeschaltet.
Nach der Anwahl des Laufwerks speichert das BDOS den Wert der
LW-Position und setzt dort die aktuelle Usernummer ein. Dadurch
entsprechend sich - BDOS-intern - FCB und Eintrag in
den ersten 12 Positionen.
Die nächsten vier Bytes sind zwischen FCB und Eintrag unterschiedlich: Da bei Fileoperationen immer mit einzelnen Records gearbeitet wird, beschreibt ein FCB - anders als ein Eintrag - keine Filegröße, sondern einen bestimmten Record.
EG und EX bilden im FCB die Nummer des Extends, in dem der zu
bearbeitende Record liegt. RC ist Anzahl von Records in
diesem Extend.
Die genaue Recordnummer innerhalb des Extends ist in der
zusätzlichen Position CR enthalten.
B1 bis Bn entsprechend genau der Blocktabelle des Eintrags. Aus dieser Blocktabelle entnimmt das BDOS während der Bearbeitung die Blocknummer für den Diskettenzugriff.
Im CP/M 1.4 ist es Aufgabe des Programms, die Eintrags- und
Recordnummer im FCB zu setzen. Soll ein bestimmter Record
innerhalb des Files erreicht werden, so muß das Programm die
Extend- und Recordnummer selbst berechnen und in den FCB
einsetzen.
Aus der absoluten Recordnummer RRN ergibt sich die Extendnummer EX
aus der Division durch 128. Der Divisionrest ist die Recordnummer CR
innerhalb des Extends. Diese Werte müssen aber immer
vor dem Öffnen gesetzt sein, damit das BDOS die richtige
Blocktabelle in den FCB überträgt.
RRN -> SRN: RRN = 128 + EX * 128 + CR SRN -> RRN: EX = RRN / 128 CR = RRN modulo 128
Alle höheren Recordnummern können im CP/M 1.4 nur sequentiell
(nacheinander) erreicht werden.
Die im CP/M 1.4 benutzte Zugriffsart auf ein File trägt
daher die Bezeichnung sequentieller Zugriff (engl. Sequential
Access). Die direkte Anwahl eines beliebigen Records ist im
sequentiellen Zugriff nicht möglich.
CP/M 2.2 bietet daher mit dem direkten Zugriff (engl. Random Access) eine weitere Zugriffsart, mit der jeder Record eines Files direkt erreicht werden kann.
Beim Random Access wird über zusätzliche Stellen im FCB eine absolute Recordnummer zwischen 0 und 65535 dem BDOS übergeben.
Zur Aufnahme der Recordnummer beim Random Access wird der
FCB ab der Position 33 um die 3 Bytes R0, R1 und R2 erweitert.
R0 und R1 enthalten die 16-Bit Recordnummer mit dem niederwertigen
Byte in R0. R2 dient bei der Umrechnung zwischen SRN
und RRN der Kennung eines Überlaufs und sollte immer auf Null
gesetzt werden.
Das BDOS berechnet aus dieser 'Random Record Number' (RRN) die 'Sequential Record Number' (SRN), bestehend aus Extendgruppe EG, Extend EX und Recordnummer CR.
Zwischen der Random Record Nummer RRN und der Sequential Record Nummer SRN besteht folgender Zusammenhang:
RRN -> SRN: RRN = EG * 32 * 128 + EX * 128 + CR SRN -> RRN: EG = RRN / 4096 = RRN / (32 * 128) EX = (RRN / 128) modulo 32 CR = RRN modulo 128
Das CP/M 2.2 erlaubt den Anschluß von bis zu 16 Laufwerken unterschiedlicher Kapazität. Die zu jedem Laufwerk gehörenden Parameter werden vom BIOS verwaltet und dem BDOS zur Verfügung gestellt.
Bei der Anwahl eines Laufwerks über das BIOS erhält das BDOS die Adresse eines Datenbereiches mit der Bezeichnung DPH. DPH ist die Abkürzung für Disk Parameter Header, was soviel wie 'Disketten-Parameter-Anfang' bedeutet.
Der DPH ist der 'Anfang' der Diskettenparameter und enthält, neben Daten, noch Verweise zu weiteren Tabellen.
Ein DPH umfasst 8 Einträge zu je 16 Bit und hat folgende Struktur:
+-----------------------------------------------------+ : XLT : NHDE : CLTK : FSCT : DIRBUF : DPB : CSV : ALV : +-----------------------------------------------------+ Byte 0/1 2/3 4/5 6/7 8/9 A/B C/D E/F mit XLT Adresse der Sektor-Verschränkungs-Tabelle (engl. X-lation Table) NHDE Nummer des letzten belegten Eintrags in der Directory der Diskette +1 (engl. Number of Highest Directory Entry) CLTK Aktuelle (zuletzt angewählte) logische Spurnummer des Laufwerks (engl. Current Logical TracK) FSCT Absolute (logische) Recordnummer des ersten Records der aktuellen Spur (engl. First Sector of Current Track) DIRBUF Adresse eines 128-Byte Buffers für Directory- Operationen (engl. DIRectory BUFfer) DPB Adresse des Disk Parameter Blocks (engl. Disk Parameter Block) CSV Adresse des Prüfsummenvektors (engl. Check Sum Vector) ALV Adresse des Belegungsvektors (engl. ALlocation Vector)
Nur NHDE, CLTK und FSCT sind wirkliche Daten, alle anderen Werte sind Verweise auf weitere Tabellen.
Die Sektor-Verschränkungs-Tabelle (XLT) dient zur Umrechnung von logischen zu physikalischen Sektornummern einer Spur. Die Länge dieser Tabelle entspricht der Anzahl logischer Sektoren die im DPB (s.u.) definiert sind.
NHDE ist die Nummer des höchsten belegten Directory-Eintrags+1
und dient der Geschwindigkeitserhöhung bei Directory-Zugriffen.
NHDE wird jeweils beim Einloggen eines Laufwerks und beim
Löschen oder Neuanlegen eines Eintrages neu berechnet. Die
Berechnung der Prüfsumme und das Suchen eines Eintrages
bleibt im BDOS auf den so abgegrenzten Directory-Bereich
beschränkt.
CLTK und FSCT dienen dem BDOS der schnelleren Berechnung der
anzuwählenden Spur- und Sektornummer bei einem Diskettenzugriff.
Das BDOS berechnet aus Block- und Recordnummer des FCB eine
absolute logische Sektornummer der Diskette. Mit der Anzahl
von logischen Sektoren pro Spur (siehe DPB) kann daraus die
Spur- und Sektornummer durch Division bestimmt werden. Da
eine Division jedoch sehr zeitaufwendig ist, wird diese Rechnung
im BDOS auf eine wiederholte Subtraktion zurückgeführt.
Von der absoluten Sektornummer wird solange die Anzahl der
Sektoren pro Spur abgezogen, bis das Ergebnis negativ wird.
Die Anzahl der durchgeführten Subtraktionen ist dann genau
die (logische) Spurnummer.
Durch Mitführen der zuletzt angewählten Spurnummer (CLTK) und
der absoluten Recordnummer des ersten Records dieser Spur
(FSCT) wird diese Rechnung im BDOS noch beschleunigt.
Das BDOS vergleicht die neue anzuwählende absolute Sektornummer
immer mit FSCT. Ist die neue Sektornummer kleiner, so
wird solange die Spurnummer CLTK dekrementiert und von FSCT
die Anzahl von Sektoren pro Spur abgezogen, bis die Sektornummer
wieder größer als FSCT ist.
In einer zweiten Schleife wird danach das Gleiche mit umgekehrten
Vorzeichen wiederholt: Es wird CLTK erhöht und zu
FSCT die Anzahl der Sektoren pro Spur addiert, bis die anzuwählende
absolute Sektornummer wieder kleiner als FSCT ist.
Dieses 'Herantasten' an die Spurnummer beschleunigt die Berechnung
der Spurnummer ganz erheblich, da auf eine Division
verzichtet werden kann.
Aus der Differenz der absoluten Sektornummer und des neuen
FSCT-Wertes berechnet das BDOS dann noch die logische Sektornummer
innerhalb der Spur.
DIRBUF ist die Adresse eines 128-Byte Puffers für Directory- Operationen. Alle Laufwerke können den selben DIRBUF benutzen, da das BDOS den Inhalt des DIRBUF bei einem Laufwerkswechsel verwirft.
Der Disk Parameter Block (DPB) ist ziemlich komplex und wird im nächsten Abschnitt getrennt besprochen. Mehrere DPH können auf ein und denselben DPB verweisen.
Im CSV sind die Prüfsummen (engl. Checksum) der einzelnen
Directory-Records gespeichert.
Pro Directory-Record ist im CSV ein Byte vorhanden, das die
Quersumme aller 128 Bytes des entsprechenden Records enthält.
Vor der Änderung eines Directory-Records wird seine Quersumme
bestimmt und mit der im CSV gespeicherten Quersumme verglichen.
Bei einer Abweichung sperrt das BDOS alle weiteren
Schreibzugriffe auf dieses Laufwerk. Näheres dazu wurde bereits
im Zusammenhang mit dem Warmstart beschrieben.
Der Allocation Vektor (ALV) bildet die Belegungstabelle (besser:
Belegungsvektor) der Diskette.
Aus dem Belegungsvektor kann das BDOS ersehen, welche Blöcke
auf der Diskette noch frei und welche belegt sind. Aus diesem
Vektor holt auch das STAT-Programm seine Information über den
noch verfügbaren Platz auf der Diskette.
Die Bezeichnung 'Vektor' deutet beim ALV auf die bitweise
Speicherung hin. für jeden Block der Diskette ist im ALV ein
Bit vorhanden, das entsprechend auf 0 (Block frei) oder 1
(Block belegt) gesetzt wird.
Die Zuordnung der Blöcke zu den Bits geschieht in absteigender
Bitnummernfolge (höchstes Bit eines Bytes zuerst) und
aufsteigender Bytefolge (erstes Byte des ALV zuerst).
Die Position eines zu einem Block gehörenden Bits läßt sich
sehr einfach berechnen:
Die Blocknummer geteilt durch 8 ergibt die Position des Bytes
innerhalb des ALV; der Divisionsrest die Nummer des Bits
innerhalb des ALV, wobei 0 das höchst- und 7 das niederwertigste
Bit bezeichnet.
Der Disk Parameter Block (DPB) beinhaltet alle Parameter, die Größe und Aufteilung der Diskette beschreiben, insbesondere die Anzahl der logischen Sektoren pro Spur, die Blockgröße, die Anzahl der Blocks auf der Diskette und die Größe der Directory.
Ein DPB umfasst 15 Bytes in folgender Aufteilung:
+----------------------------------------------------------+ : SPT : BSH : BLM : EXM : DSM : DRM: AL0 : AL1 : CKS : OFF : +----------------------------------------------------------+ 0/1 2 3 4 5/6 7/8 9 A B/C D/E 16 8 8 8 16 16 8 8 16 16 (Die erste Zahlenreihe gibt die Position des Parameters innerhalb des DPB an und die zweite, ob es sich um einen 8 oder 16-Bit Wert handelt.) mit SPT Anzahl der logischen Sektoren pro Spur (engl. Sectors Per Track) BSH 2-er Exponent der Blockgröße (engl. Block SHift factor) BLM Anzahl von Records pro Block -1 (engl. Block Length Mask) EXM Anzahl der Extends pro Eintrag -1 (engl. Extend Mask) DSM Höchste Blocknummer der Diskette (engl. Data Storage Maximum) DRM Höchste Eintragnummer in der Directory (engl. DiRectory Maximum) AL0 Erstes Byte des ALV (engl. Allocation Vector byte 0) AL1 Zweites Byte des ALV (engl. Allocation Vector byte 1) CKS Anzahl der zu prüfenden Directory-Records (engl. ChecK vector Size) OFF Anzahl der reservierten Spuren am Anfang der Diskette (engl. track OFFset)
Die Verwendung des SPT-Wertes wurde bereits im letzten Abschnitt beschrieben. SPT entspricht auch der Länge der Sektor- Verschränkungs-Tabelle (XLT).
BSH und BLM beinhalten beide die Blocklänge BLS (engl. BLock Size). Durch diese 'doppelte' Angabe der Blocklänge werden bestimmte BDOS-interne Rechenoperationen vereinfacht.
Zwischen der Blocklänge in Bytes und den beiden Werten BSH und BLM gilt folgender Zusammenhang:
BLS BSH BLM 1024 3 7 2048 4 15 4096 5 31 8192 6 63 16384 7 127
kurz
BLS = 128 * 2^BSH = 128 * (BLM+1)
In EXM wird die Anzahl von Extends pro Directory-Eintrag
definiert.
EXM ist abhängig von der Blockgröße und der Anzahl der Blöcke (DSM+1)
pro Diskette. Je nachdem, ob weniger als 256 Blöcke (8-Bit
Blocknummern) oder mehr als 255 Blöcke (16-Bit Blocknummern)
definiert sind, gibt es für EXM jeweils zwei Möglichkeiten:
(Die erste EXM-Spalte gibt die Werte für 8-Bit Blocknummern,
die zweite für 16-Bit Blocknummern an.)
BLS EXM 8 Bit EXM 16 Bit 1024 0 - 2048 1 0 4096 3 1 8192 7 3 16384 15 7
DSM enthält die Anzahl von Blöcken pro Diskette -1 bzw. die
höchste Blocknummer der Diskette.
Die Gesamtkapazität der Diskette in Bytes ergibt sich aus dem
Produkt von BLS und (DSM+1); für den Allocation Vector müssen
(DSM / 8) + 1 Bytes reserviert werden.
Rein theoretisch ist zwar eine Maximalkapazität von einem Gigabyte (65536 Blöcke a 16 kbyte) denkbar, diese ist aber durch die Verwaltung der Recordnummern im 16-Bit Format auf 65536 Records, also 8 Megabyte (65536 * 128 Bytes) beschränkt.
04/2019: Unter CPM 2.2 sind nachgewiesen aufgrund der 16Bit-Arithmetik nur Laufwerkwerke bis maximal 8 Mbyte nutzbar!1) Mit anderen BDOS-Varianten können größere Laufwerke genutzt werden.2)
DRM+1 ist die Anzahl der Directory-Einträge der Diskette. Da die Eintragsnummern - genauso wie die Blocknummern - von Null an gezählt werden, enthält DRM den um eins verminderten Wert.
AL0 und AL1 bilden die ersten beiden Bytes des Allocation
Vectors und müssen daher, wie der ALV, als Bitvektor gesehen
werden.
für jeden als Directory-Bereich reservierten Block der Diskette
muß das entsprechende Bit in diesem Vektor gesetzt
werden. Das höchste Bit von AL0 entspricht dem ersten Block
der Diskette (Block Nummer 0) und das letzte Bit in AL1 dem
sechzehnten Block (Block Nummer 15). Da AL0 und AL1 nur einen
16-Bit Vektor bilden, ist die Anzahl der maximal möglichen
Directory-Blöcke auf 16 beschränkt.
CKS kennzeichnet die Länge des Prüfsummen-Vektors (CSV) und
damit die Anzahl der zu prüfenden Directory-Records, die sich
aus der Beziehung CKS = (DRM + 1) / 4 ergibt.
Falls eine Prüfung der Directory nicht erwünscht oder, wie
z.B. bei Festplattenlaufwerken, nicht notwendig ist, kann
CKS auch Null sein.
OFF ist die Anzahl der reservierten Spuren auf der Diskette. Dieser Wert ist für das BDOS unerheblich, wird aber vor dem Setzen der physikalischen Spurnummer zur errechneten logischen Spurnummer (CLTK) addiert.
Alle BDOS-Funktionen werden über den Sprungbefehl zum BDOS an der Adresse BOOT+0005H erreicht. Dadurch ist, unabhängig von der tatsächlichen Lage des BDOS im Speicher, die Betriebssystem- Schnittstelle für alle CP/M-Rechner identisch.
Ein Programm lädt die gewünschte Funktionsnummer in das C-Register des Prozessors und führt danach ein 'CALL' nach BOOT+0005H aus. 8-Bit Funktionsparameter werden im E-Register, 16-Bit Parameter im Registerpaar DE übergeben. Das BDOS führt daraufhin die gewünschte Funktion aus und gibt einen 8- (im Register A) oder 16-Bit Funktionswert (im Registerpaar HL) zurück.
Das BDOS im CP/M 2.2 bietet insgesamt 39 verschiedene Funktionen zur Zeichen- und Dateibearbeitung, die im folgenden beschrieben werden. Neben der Funktionsnummer und der englischen und deutschen Funktionsbezeichnung ist auch die Registerbelegung angegeben.
'I:' bezeichnet die notwendige Registerbelegung beim Aufruf des BDOS, 'O:' die vom BDOS zurückgelieferten Registerwerte.
Nummer: | 0 |
---|---|
Bezeichnung: | System Reset Warmstart |
I: | C = 00H |
O: | - |
Ausgeführte Funktion:
Direkter Sprung zur Warmstartroutine im BIOS. Der Warmstart lädt den CCP und das BDOS neu in den Speicher und übergibt die Kontrolle an den CCP. Die Funktion 0 entspricht einem Sprung zur Adresse BOOT.
Nummer: | 1 |
---|---|
Bezeichnung: | Console Input Consoleneingabe |
I: | C = 01H |
O: | A = Zeichen von der Console |
Ausgeführte Funktion:
Console Input holt das nächste Zeichen von der Console und
sendet darstellbare Zeichen über die Consolenausgabe als Echo
zurück.
Die Steuerzeichen 'Carriage Return' (ASCII 0DH), 'Line Feed'
(ASCII 0AH) und 'Backspace' (ASCII 08H) werden ebenfalls
ausgegeben. Das 'Tab'-Zeichen (ASCII 09H) erzeugt auf der
Ausgabe soviele Leerzeichen, wie zur Erreichung der nächsten
durch 8 teilbaren Spaltenposition (Tabulator-Position) notwendig
sind.
Bei Erkennung von CTRL-S (ASCII 13H) wartet Console Input auf
ein weiteres Zeichen und hält dadurch die Verarbeitung an.
CTRL-C (ASCII 03H) führt zu einem direkten Sprung nach BOOT,
was im allgemeinen einen Warmstart auslöst.
Die Console Input Funktion ist erst beendet, wenn tatsächlich
ein Zeichen von der Console erkannt wurde.
Nummer: | 2 |
---|---|
Bezeichnung: | Console Output Consolenausgabe |
I: | C = 02H E = ASCII-Wert |
O: | - |
Ausgeführte Funktion:
Der ASCII-Wert vom Register E wird zur Console ausgegeben und die Consoleneingabe überprüft. Vor der eigentlichen Zeichenausgabe wird der Consolenstatus über die BDOS-Funktion 11 überprüft. Alle dort beschriebenen Verhaltensweisen gelten daher auch für die Consolenausgabe. Die Behandlung des 'Tab'- Zeichens ist wie in Funktion 1.
Nummer: | 3 |
---|---|
Bezeichnung: | Reader Input 'Reader'-Eingabe |
I: | C = 03H |
O: | A = Zeichen vom 'Reader'-Kanal |
Ausgeführte Funktion:
Reader Input holt das nächste Zeichen vom 'Reader'-Kanal,
stellt es aber nicht auf der Console dar.
Das BDOS führt keine weitere Zeichenbehandlung durch, sondern
benutzt direkt die entsprechende BIOS-Funktion.
Nummer: | 4 |
---|---|
Bezeichnung: | Punch Output 'Punch'-Ausgabe |
I: | C = 04H E = ASCII-Wert |
O: | - |
Ausgeführte Funktion:
Das BDOS verzweigt direkt zur entsprechenden BIOS-Funktion, die das Zeichen zum 'Reader'-Kanal ausgibt.
Nummer: | 5 |
---|---|
Bezeichnung: | List Output Druckerausgabe |
I: | C = 05H E = ASCII-Wert |
O: | - |
Ausgeführte Funktion:
Das BDOS verzweigt direkt zur entsprechenden BIOS-Funktion, die das Zeichen zum 'List'-Kanal ausgibt. Der 'List'-Kanal ist im CP/M als Druckerausgabe definiert.
Nummer: | 6 |
---|---|
Bezeichnung: | Direct Console I/O Direkte Consolenein/ausgabe |
I: | C = 06H E = 0FFH für Consoleneingabe E = 0FEH für Consolen-Status prüfen E = ASCII Zeichen zur Consolenausgabe sonst |
O: | A = Zeichen von der Console (falls E = 0FFH) A = Consolen-Status (falls E = 0FEH) A = Undefiniert sonst |
Ausgeführte Funktion:
über die direkte Consolenein/ausgabe kann die Console unter Umgehung des BDOS erreicht werden. Alle Sonderbehandlungen von Zeichen, wie sie das BDOS bei den Funktionen 1 und 2 vornimmt, werden unterdrückt. Die direkte Consolenein/ausgabe benutzt direkt die entsprechenden BIOS-Funktionen.
Nummer: | 7 |
---|---|
Bezeichnung: | Get I/O Byte I/O Byte holen |
I: | C = 07H |
O: | A = I/O-Byte von der Adresse BOOT+0004H |
Ausgeführte Funktion:
Das BDOS gibt den Inhalt der Speicherstelle BOOT+0004H im A-Register zurück. über das I/O-Byte kann im BIOS eine weitere Aufschlüsselung der Ein/Ausgabekanale vorgenommen werden, dies hat jedoch keinen Einfluss auf das BDOS.
Nummer: | 8 |
---|---|
Bezeichnung: | Set I/O Byte I/O Byte setzen |
I: | C = 08H E = I/O-Byte |
O: | - |
Ausgeführte Funktion:
Der im E-Register ubergebene Wert wird in der Speicherstelle BOOT+0004H abgelegt. Damit kann ein Programm die Zuordnung der Ein/Ausgabekanäle beeinflussen, falls das I/O-Byte vom BIOS beachtet wird.
Nummer: | 9 |
---|---|
Bezeichnung: | Print String Zeichenkette ausgeben |
I: | C = 09H DE → Zeichenkette |
O: | - |
Ausgeführte Funktion:
Die einzelnen Zeichen der Zeichenkette werden über die BDOS-Funktion 2 zur Console ausgegeben. Die weitere Zeichenbehandlung ist daher identisch mit der Consolenausgabe. Das Zeichen '$' zeigt das Ende der Zeichenkette an und wird nicht ausgegeben.
Nummer: | 10 |
---|---|
Bezeichnung: | Read Console Buffer Zeile von der Console einlesen |
I: | C = 0AH DE → Zeilenbuffer |
O: | Zeilenbuffer gefüllt mit den eingegebenen Zeichen |
Ausgeführte Funktion:
Alle folgende Zeichen von der Consoleneingabe werden in den
Zeilenpuffer ubernommen und über die Consolenausgabe dargestellt.
Die Eingabe ist beendet, wenn entweder eines der Zeichen
'Carriage Return' (ASCII 0DH) oder 'Line Feed' (ASCII 0AH)
erkannt wird oder das Ende des Buffers erreicht ist.
Die Bufferlänge erhält das BDOS im ersten Byte des Zeilenbuffers
mitgeteilt. Nach Beendigung der Funktion steht im zweiten
Byte die Anzahl der tatsächlich eingegebenen Zeichen,
gefolgt von den eigentlichen Zeichen. Die Bufferlänge ist
damit immer um zwei Bytes größer als die maximale Zeilenlänge.
während der Eingabe werden vom BDOS verschiedene Steuerzeichen
zur Editierung der Zeile erkannt:
CTRL-C (ASCII 03H) führt zu einem Warmstart, falls es als erstes Zeichen eingegeben wird, CTRL-E (ASCII 05H) beginnt eine neue Zeile auf der Consolenausgabe, ohne jedoch den Zeilenbuffer zu ändern. CTRL-H (ASCII 08H) löscht das jeweils letzte Zeichen sowohl im Buffer als auch auf der Consolenausgabe, CTRL-J (ASCII 0AH) beendet die Zeileneingabe und sendet ein 'Carriage Return' (ASCII 0DH) zur Consolenausgabe. CTRL-M (ASCII 0DH) hat die selbe Wirkung wie CTRL-J CTRL-P (ASCII 10H) schaltet die parallele Druckerausgabe zur Consolenausgabe (Protokollfunktion) ein oder aus. CTRL-R (ASCII 12H) beginnt eine neue Ausgabezeile und zeigt die bisher eingegebene Bufferzeile nochmals an. CTRL-U (ASCII 15H) beginnt eine neue Ausgabezeile und startet die gesamte Zeileneingabe neu. Die bisher ausgegebenen Zeichen werden nicht gelöscht. CTRL-X (ASCII 18H) löscht die bisher eingegebenen Zeichen sowohl im Buffer als auch auf der Consolenausgabe. Die Zeileneingabe wird daraufhin neu begonnen. DEL (ASCII 7FH) löscht das jeweils letzte Zeichen des Buffers und gibt es nochmals auf der Console aus.
Nummer: | 11 |
---|---|
Bezeichnung: | Get Console Status Consolenstatus testen |
I: | C = 0BH |
O: | A = FFH, falls ein Zeichen von der Console ansteht = 00H sonst |
Ausgeführte Funktion:
Es wird gepruft, ob ein Zeichen von der Console zur Eingabe
ansteht. Die Consolenstatus-Funktion speichert ein anstehendes
Zeichen zwischen und gibt es beim nächsten Consoleneingabe-
Aufruf als Zeichen zurück.
Das Zeichen CTRL-S wird von dieser Funktion erkannt, die
daraufhin auf ein weiteres Zeichen wartet. CTRL-C bewirkt
einen direkten Sprung nach BOOT, was im allgemeinen zu einem
Warmstart führt.
Falls ein anstehendes Zeichen nicht 'abgeholt' wird, gibt die
Consolenstatus-Funktion immer FFH zurück, ohne den Status der
Console wirklich zu testen. In diesem Fall werden die Steuerzeichen
CTRL-S und CTRL-C nicht mehr erkannt!
Nummer: | 12 |
---|---|
Bezeichnung: | Return Version Number CP/M Versionsnummer zurückmelden |
I: | C = 0CH |
O: | HL = 0022H (bei CP/M 2.2) |
Ausgeführte Funktion:
über die BDOS-Funktion 12 können Programme auf eine bestimmte CP/M Version angepasst werden. Im H-Register wird für CP/M der Wert 00H, für MP/M (multi-tasking CP/M) der Wert 01H zurückgegeben. Das L-Register bezeichnet dann die genaue Versionsnummer. L = 00H bezeichnet alle Versionen vor CP/M 2.0, die Werte 20H, 21H, 22H usw. die entsprechenden CP/M Versionen 2.0. 2.1, 2.2 usw.