Die Technik hinter CP/M
So, weiter geht es mit einer Serie von Artikeln zu historischen Computerthemen. Nachdem ihr schon etwas über die Geschichte von CP/M erfahren habt, habe ich die letzte Woche an einem ziemlich langen Artikel über die Technik von CP/M gearbeitet, den es auch komplett auf der Website gibt. Die weiteren Teile findet ihr hier in den nächsten Tagen. Also morgen den zweiten Teil.
Hier alle Teile die in den nächsten Tagen erscheinen:
Teil 1 behandelt den Aufbau des Speichers und des Dateisystems
Teil 2 behandelt den Aufbau einer Diskette und des Rechners, Bildschirm und Tastatur
Teil 3 behandelt die BDOS-Funktionen, den Kommandointerpreeter, User Befehl und die Geräte.
Teil 4: Über CP/M 3, andere Versionen und warum es heute noch neue CP/M Rechner gibt.
CP/M – Control Program for Microcomputers – besteht aus drei Teilen, man könnte auch sagen drei Schichten. Während dies heute normal ist (Internetdatenverkehr besteht zum Beispiel aus bis zu sieben Schichten), war dies damals eine revolutionäre Neuerung. Vorher waren Betriebssysteme mehr oder weniger monolithisch. Die drei Schichten bauen aufeinander auf und sind:
- CCP: Console Command Processor: die Eingabeschnittstelle mit der der Benutzer Befehle eintippen kann.
- BDOS: Das BASIC Disk Operation System enthält eine Sammlung von 41 Routinen, mit denen man Dateien verwalten kann, aber auch Dinge auf dem Bildschirm oder Drucker ausgeben kann und Zeichen von der Tastatur einlesen kann.
- BIOS: Das BASIC Input / Outputsystem kümmert sich vor allem um den physikalischen Zugriff auf Diskettenlaufwerken.
Speicheraufbau
Beim Start werden die drei Teile an das Ende des Speichers geladen. Das „Ende“ muss nicht der Maximalspeicherausbau sein. Zum einen läuft CP/M auch mit weniger Speicher – die letzte Version von CP/M, 2.2 die ohne Bankswitching arbeitete, mit minimal 20 KByte – zum anderen können sich oben noch Speicherbereiche befinden, die zur Hardware gehören, bei den Amstrad PC belegte z.B. der Bildschirmspeicher die letzten 16 KByte, darunter kamen Betriebssystemdaten (die des ROM-Betriebssystems), sodass nur etwa 44 KByte übrig blieben. Die Reihenfolge ist aber fix: ganz oben ist das BIOS, dann folgt das BDOS und zuletzt der CCP. Diese Reihenfolge ist so gewählt, weil ein Programm, nachdem es geladen wurde den CCP überschreiben kann. Er wird bei einem Rücksprung ins BDOS automatisch neu von der Diskette geladen.
CP/M lieferte das Programm Movcpm mit. Dieses konnte den Start von CP/M in Vielfachen einer Page (256 Bytes) verschieben, wenn man zum Beispiel einen Speicherbereich für ein Programm brauchte, der persistent war, also auch nach Programmende die Daten behielt. Das waren meist Treiber für zusätzlich erworbene Hardware.
Ganz am Anfang des Speichers findet man zum einen die Restarts: Das sind beim 8080/Z80 Prozessor Routinen, die mit einem Befehl ohne Adressangabe angesprungen werden können. Sie werden für häufige Softwareroutinen genutzt, z.B. um das Betriebssystem-ROM einzublenden oder fürs Bankswitching. Einige Restarts nutzte CP/M selbst. Danach folgten einige Verwaltungsinformationen, so z.B. ab Adresse 80H (128 dezimal, im Folgenden arbeite ich meist mit Hexadezimalziffern, weil diese meist gerade sind) die Eingabezeile aus der ein Programm die Startparameter wie übergebene Dateien herausfischen konnte.
Den Bereich zwischen 100H und dem Anfang des CCP bezeichnete man als TPA – Transistent Programm Area, weil wenn ein Programm beendet war dieser Bereich wieder frei war. Die Größe der TPA legte fest wie viel Arbeitsspeicher Anwendungsprogramme zur Verfügung hatten. In ihr wurden sie ausgeführt.
Ein Programm für CP/M wurde immer an die Adresse 100H geladen. CP/M erkannte ein ausführbares Programm an der Endung „.com“. Es konnte dann den ganzen Speicher bis zum Anfang des BDOS nutzen. Viele Implementierungen gaben diesen Speicher auch beim Start aus:
MinZ_C #47 – Z8S180 @ 33.333MHz 1MB RAM (0ws) 512KB Flash „ROM“ (1ws)
A: RAMdisk 948 KB
C: SD Card 8192 KB
P: ROMdisk 496 KB
CP/M 2.2 64K (57K [+2K CCP] TPA) – BIOS V1.3 SUN JAN 1/01 5:28:34
A>
In diesem Falle nutzt CP/M die vollen 64 KByte, für Programme stehen 57 KByte zur Verfügung bzw. wenn der CCP überschrieben wird sind es sogar 59 KByte. Das ist viel, bedenkt man, dass der Intel 8080 maximal 64 KByte adressieren kann.
Das war einer der wichtigsten Vorteile von CP/M. Das Betriebssystem brauchte sehr wenig Speicher. Das BIOS belegte typisch 4 KByte, das BDOS unter CP/M 2.2 zwischen 2,8 und 3,5 KByte, das hing davon ab, welche Hardware tatsächlich verbaut und unterstützt werden musste. Fehlte z.B. eine serielle Schnittstelle so fielen Routinen weg. Der CCP war immer 2 KByte groß. Dazu kamen dann noch hardwarespezifische Dinge. Die meisten Systeme hatten den Bildschirmspeicher im Adressraum, der weitere 2 bis 4 KByte belegte. Real konnte ein CP/M Rechner mit reinem Textbildschirm zwischen 52 und 54 KByte von 64 KByte adressierbarem Speicher freihaben.
Das waren über drei Virtel des gesamten Speichers und damals enorm viel. Neben Rechnern die CP/M von der Diskette booteten, gab es auch Rechner mit einem BASIC Interpreter, bei denen war dieser zugleich das Betriebssystem und diese hatten viel weniger Speicher frei. Beim populären C-64 waren es 38 KByte, beim Amstrad CPC 42,6 KByte. Der Unterschied von 10 bis 20 KByte erscheint heute gering, machte in der Praxis aber viel aus, denn viele Anwendungen konnten Daten (Texte, Datenbanken, Spreadsheets) bearbeiten, die größer als der Arbeitsspeicher waren, konnten im Speicher aber nur einen kleinen Teil unterbringen und wenn der verfügbare Speicher voll wurde, dann wurde dieser Teil auf die Diskette ausgelagert und das dauerte. Zudem waren diese Programme so compiliert, das sie auch auf kleineren Systemen liefen also Rechnern mit weniger als 64 KByte Speicher. Nutzen mehr Arbeitsspeicher aber dann für die Daten.
Als mit der Version 3.0 noch Bankswitching eingeführt wurde, konnten BIOS und BDOS in eine andere Bank verschoben werden und dann konnte man 61 bis 63 KByte der 64 KByte nutzen. Das waren über 90 Prozent des physikalisch ansprechbaren Speichers!
Aufbau des Dateisystems
Die wichtigste Eigenschaft von CP/M war die Verwaltung von Disketten. Es war der zentrale Punkt eines Betriebssystems und steckte so auch bei anderen Betriebssystemen im Namen wie PC-DOS oder QDOS. Das „D“ steht dabei für „Disk“.
Im Dateisystem findet man die meisten Altlasten von CP/M. Es entstand zur Ansteuerung von 8 Zoll Floppydisklaufwerken, genauer gesagt dem Typ IBM 3740. Diese 8 Zoll (20,32 cm) Diskette hatte 73 Spuren, jede Spur bestand aus 26 Sektoren die jeweils 128 Bytes groß waren. Sie fasste also genau 242.944 Bytes oder 237,25 KByte. Mit der Version 2.0 unterstützte CP/M auch 5,25 und spätere Floppylaufwerke mit andern Formfaktoren. Die große Änderung war, das hier das Format nicht standardisiert war. Es gab zwei Schreibdichten, „einfache“ oder „doppelte“. Es gab zuerst Laufwerke mit 35 oder 40 Spuren, dann folgten welche mit 70 oder 80 Spuren. Dann gab es noch einen Unterschied in den Laufwerken: Ein Laufwerk konnte nur einen Schreib-/Lesekopf haben, dann musste man, um die Rückseite einer Diskette zu bespielen, diese manuell umdrehen oder es konnten beide Seiten simultan beschrieben werden, dann war diese eine Disk mit der doppelten Kapazität einer Seite.
Bis hierher liegen die Unterschiede in der Physik, also ein Laufwerk für 40 Spuren wird nie eine Diskette mit 80 Spuren lesen können. Dann hatte die Computerfirma aber die Freiheit zu bestimmen, wie eine Spur formatiert werden soll. Unformatiert fasste eine Spur immer 3.125 Bytes bei einfacher und 6.250 Bytes bei doppelter Schreibdichte. Es gab Sektoren mit 256 Bytes, am verbreitetsten waren 512 Bytes und einige Systeme hatten 1.024 Byte große Sektoren. Die Größe war abzuwägen. Zu jedem Sektor gab es auf der Disk Verwaltungsinformationen und nach jedem Sektor folgte eine unbeschriebene Zone um der Anwendung Zeit zu geben die Daten zu verarbeiten. Je mehr Sektoren man hatte, desto mehr Platz nahmen diese Bestandteile von der unformatierten Kapazität weg. Systeme mit 256 Byte Sektoren hatten typisch 13-16 Sektoren pro Spur (3,25-4 KByte), bei 512 Byte Spuren waren es acht oder neun Sektoren (4-4,5 KByte) und bei 1 KByte gingen 5 Sektoren auf eine Spur, also 5 Kbyte/Spur.
Der Nachteil war das man jeweils für das Schreiben und Lesen eines Sektors Speicher reservieren musste, bei 1 KByte großen Sektoren sind das 2 KByte, die vom nutzbaren Speicher abgingen, man erkaufte sich also mehr Kapazität auf der Diskette mit einem höheren Arbeitsspeicherverbrauch, der meiner Erfahrung nach immer knapper war als Platz auf der Floppy. Es gab daher nur wenige Systeme die 1 KByte große Sektoren nutzten. CP/M selbst machte diese Änderung nicht mit, das BDOS als Anwendungsschnittstelle arbeitete immer mit 128 Byte Sektoren wie sie beim ersten Laufwerk üblich waren. Das BIOS musste diese dann an passender Stelle in einen der größeren Sektoren umkopieren. Beim linearen Lesen machte dies wenig aus, doch wenn eine Anwendung auf die Sektoren nicht linear zugriff, musste jeweils ein größerer Sektor gelesen oder geschrieben werden, auch wenn sich nur ein Teil des Inhaltes änderte.
Auf diesen 128 Byte als logische Sektorgröße basierte auf der Verzeichniseintrag. In einem Feld wurde eingetragen wie viele 128 Byte Sektoren die Datei umfasste. Dabei war Schluss bei 128 Sektoren (80h). Das entsprach 16 KByte. Jede Datei die größer als 16 KByte war belegte so mehrere Verzeichniseinträge. Das war insofern ungeschickt, weil CP/M außer dem logischen Sektor, Record genannt, auch größere Verwaltungsinformationen auf BDOS Ebene kannte. Die wichtigste war der Block. Eine Datei belegte immer einen Block, selbst wenn sie nur 1 Byte lang war. Der Grund eine größere Einheit einzuführen war, dass CP/M intern eine Tabelle hatte, in der sie vermerkte, welcher Block auf der Diskette frei war. Sonst hätte bei jeder Schreiboperation das ganze Verzeichnis durchsucht werden müssen um zu sehen, wo auf der Diskette noch Platz frei war. Hätte diese Tabelle auf Records basiert so wäre sie unverhältnismäßig groß geworden. Die folgende Ausgabe gibt die logischen Verzeichnisparameter eines CP/M-Systems wieder:
C>stat dsk:
A: Drive Characteristics
7584: 128 Byte Record Capacity
948: Kilobyte Drive Capacity
256: 32 Byte Directory Entries
0: Checked Directory Entries
512: Records/ Extent
32: Records/ Block
32: Sectors/ Track
0: Reserved Tracks
C: Drive Characteristics
65536: 128 Byte Record Capacity
8192: Kilobyte Drive Capacity
768: 32 Byte Directory Entries
0: Checked Directory Entries
512: Records/ Extent
64: Records/ Block
4: Sectors/ Track
0: Reserved Tracks
Relevant für die Tabelle ist die Zeile mit „Record Capacvity“. Man sieht das (bei 128 Byte Sektoren) man bei einer typischen Diskette mit einer formatierten Kapazität von 160 bis 800 KByte mehrere Tausend Einträge hätte, bei einer Festplatte (hier: 8 MByte) erreicht diese Tabelle das Maximum mit 65536 Records, mehr kann CP/M nicht verwalten. Indem aber 32 bzw. 64 Records pro Block zusammengefasst wurden, wurde die Tabelle viel kleiner. Typische Blockgrößen waren:
Typ | Kapazität unformatiert | Kapazität formatiert | Blockgröße |
---|---|---|---|
Diskette SD/SS | 250 KB | 160 – 180 KB | 1 KByte |
Diskette DD/SS / SD/DS | 500 KB | 320 – 360 KB | 2 KByte |
Diskette DD/DS | 1000 KB | 640 – 800 KB | 4 KByte |
Festplatte | >=10 MB | 8.192 KB, aber mehrere Partitionen pro Platte | 8 KByte |
Im BIOS gab es noch weitere Parameter, der physikalischen Formatierung, mit denen der Programmierer der das BDOS als Schnittstelle nutzte nichts zu tun hatte. Sie steckten in einem Definitionsblock, sodass sie austauschbar waren. Bei meinem Amstrad CPC gab es z.B. drei Diskettenformate – das IBM Format für den Datenaustausch, das CP/M-Format und das Datenformat. Bei letzterem entfielen die Spuren auf denen CP/M untergebracht war. Als ich dann noch eine Floppy eines Fremdherstellers kaufte, kannte CP/M nach einer Anpassung auch dessen Format, obwohl dieses Laufwerk 720 anstatt maximal 180 KByte pro Diskette nutzte,