Die Technik hinter CP/M (3)

Loading

Das ist der vorletzte von vier Teilen über das Innenleben von CP/M. Erschienen sind:

Teil 1 behandelt den Aufbau des Speichers und des Dateisystems

Teil 2 behandelt den Aufbau einer Diskette und des Rechners, Bildschirm und Tastatur

und sie lesen gerade:

Teil 3 behandelt die BDOS-Funktionen, den Kommandointerpreeter, User Befehl und die Geräte.

morgen erscheint dann:

Teil 4:  Über CP/M 3, andere Versionen und warum es heute noch neue CP/M Rechner gibt.

Die BDOS Funktionen

Die Kommunikation mit dem BDOS erfolgte mit dem Aufruf einer bestimmten Adresse (5). Als Übergabeparameter gab es immer die Funktionsnummer im C-Register. Daten, die an BDOS übergeben werden – im unteren Beispiel die Adresse eines auszugebenden Strings – werden im DE-Registerpaar als Adresse übergeben, Rückgabewerte nach Verlassen der Funktion stehen im HL-Registerpaar. Das folgende Beispiel ist das Hello-World Programm das nur diesen Text ausgibt. Es ist nur 25 Bytes lang, wobei es noch wenn ich aus Didaktischen Gründen nicht das Programmende durch einen Warmstart ausgelöst hätte, sondern nur einen Restart 0 nochmals 4 Bytes kürzer sein könnte. Der Quelltext (auf dem PC geschrieben) ist dieser:

tpastart equ 100h ; Definition TPA Start

bdos equ 5 ; Definition BDOS Einsprungpunkt

conout equ 9 ; Funktion 9 zum Ausgeben eines Strings auf dem Bildschirm

wstart equ 0 ; Laedt BDOS vom der Platte und beendet Programm

org tpastart

mvi c,conout ; Funktion muss im C Register sein

lxi d,helloworld ; Ausgabestring im DE Register

call bdos ; Ausgabe

mvi c,wstart

call bdos ; Programmende (ein RST 0 hätte es auch getan)

helloworld: db ‚Hallo Welt!$ ; Zeichenkette terminiert mit Dollarzeichen

end

Der Prozess der Erzeugung eines ausführbaren Programms ist etwas lang. Zuerst habe ich den Quelltext vom PC auf das CP/M System übertragen, dann mit ASM übersetzt wobei eine .HEX Datei entsteht. Der Befehl LOAD lädt dieses an die Startadresse und konvertiert es in eine .com Datei die man dann ausführen kann:

A>pcget bdos.asmCP/M Ausgabe im Terminal

Get a File from a host using XMODEM or XMODEM-1K on ASCI 1

+++Note – Old file has been deleted+++

Waiting for block # 07

Transfer complete

A>asm bdos

CP/M ASSEMBLER – VER 2.0

0119

000H USE FACTOR

END OF ASSEMBLY

A>load bdos

FIRST ADDRESS 0100

LAST ADDRESS 0118

BYTES READ 0019

RECORDS WRITTEN 01

A>bdos

Hallo Welt!

A>

Schon damals fragte ich mich, warum Gary Kildall das Dollarzeichen ($) als String-ende nahm. Eine Theorie die es gibt, ist das dies von seinen Erfahrungen mit DEC Großrechnern herrührte. Vieles von CP/M hat er vom Betriebssystem DECSystem-10 einer PDP-30 übernommen, so wie Laufwerksbuchstaben. Ich fand die Wahl für ein Betriebssystem, das zuerst einmal für US-Kunden gedacht war, nicht optimal. Drot kommt das Dollarzeichen dann doch oft in Texten vor. Idealerweise hätte man wohl ein nichtdruckbares Zeichen wie Nul (Code 0) oder End of File (Code 27) genommen. Für den Fall das es ein eintippbares Zeichen sein musste, wären mir andere selten genutzte eingefallen wie „@“, „^“ oder „`“ (Email wurde erst 10 Jahre nach CP/M eingeführt, sodass der Klammeraffe @ damals kaum genutzt wurde). Alle diese Zeichen kommen sowohl in Programmiersprachen, wie auch US-Texten kaum vor.

CP/M bekam mit jeder Version neues BDOS Funktionen, beim populären CP/M 2.2 waren es 41, wobei zwei aber gekennzeichnet waren mit „Nicht mehr verwenden“. Die meisten Funktionen hatten mit der Verwaltung von Dateien, Disketten und Verzeichnissen zu tun. Dazu gab es Funktionen für die logischen Geräte Bildschirm, Tastatur, Drucker, Leser und Stanzer.

Der Kommandointerpreter

Der CCP (Console Command Processor) war die Benutzerschnittstelle von CP/M. Er war immer 2048 Bytes lang (alle CP/M Programme hatten eine Länge von Vielfachem einer Page also 256 Bytes). Er verfügte über nur wenige eingebaute Befehle:

  • Dir zeigt das Verzeichnis oder einzelne Dateien an
  • Type Gibt den Inhalt einer Textdatei auf dem Bildschirm aus
  • ERA löscht Dateien
  • Ren benennt Dateien um
  • User: wechselt den User-Bereich (siehe unten)
  • Load Lädt eine Hex Datei in de Speicher und speichert sie als ausführbare com-Datei
  • Save speichert einen Speicherauszug ab 100h in einer Datei

Man konnte nur das letzte Zeichen oder die ganze Zeile bei der Eingabe löschen, Cursorbewegungen in der Eingabezeile waren nicht möglich. Gab man einen Dateinamen ein, der nicht den obigen Befehlen entsprach, so suchte der CCP nach einer Datei mit der Endung .com und lud sie in den Speicher und startete sie. Danach konnte der CCP, der unter dem BDOS lag, überschrieben werden. Er wurde bei einem Warmstart (Laden des BDOS von der Diskette) automatisch wieder geladen. Das ergab 2 KByte mehr Speicher.

Der User Befehl

Eine Besonderheit von CP/M ist das User-Kommando. Es gab 16 User mit den Nummern 0 bis 15. Bei jeder Datei wurde gespeichert, welcher User sie anlegte. Warum dieses Konstrukt eingeführt wurde, ist mir ein Rätsel. Vielleicht ist es eines der Dinge die Gar Kildall übernahm – vieles an CP/M wurde von den Betriebssystemen von DEC für Großrechner abgeschaut. Ich dachte auch eine Zeitlang, der Befehl stammte aus MP/M – eine CP/M Version für mehrere Nutzer, aber die kam erst heraus, als es das User Kommando schon gab.

Bei einer großen Diskette können schon mal mehrere Hundert Dateien im Verzeichnis stehen. CP/M speichert zudem alles in Großbuchstaben, was das Lesen nicht erleichtert. Dann den Überblick zu behalten ist schwer. Das mag eine Erklärung für die User Bereiche gewesen sein. Aber man hatte das Konzept nicht richtig durchdacht, denn wenn man den User Bereich wechselte, sah man nicht nur die Dateien des aktuellen User Bereichs, nein, man konnte auch auf keine anderen Dateien in anderen User-Bereichen zugreifen. Wie aber kopiert man Dateien und Programme zwischen den Usern? Die Lösung war folgende:

a>PIP

*^C

A>User 1

A>Save 28 pip.com

Man startete das Programm PIP zum Kopieren von Dateien, das mit dem Parameter [Gnn] auch die Dateien von anderen Usern kopieren konnte, brach es ab, wechselte den User und speichere es – es war immer noch im Speicher – erneut ab. PIP existierte so zweimal einmal im User Bereich 0 und einmal in 1. Ich denke mit wenig mehr Aufwand hätte man es so machen können, das Dateien im Userbereich 0 immer von allen Usern ausgeführt werden können und ein Directory Befehl der auch Dateien eines anderen User-Bereichs anzeigt, wäre auch nicht schlecht gewesen

Geräte

Diskettenlaufwerke und Festplatten sprach man mit Buchstabe+Doppelpunkt an, also z.B. A:. Neben diesen 15 Laufwerken kannte CP/M aber auch noch andere Geräte (Devices) wobei es unterschied zwischen logischen und physikalischen Geräten. Ein logisches Gerät hatte eine feste Bezeichnung, aber der Benutzer konnte entscheiden, welches physikalische Gerät sich dahinter verbarg, das Geschah mit dem Programm STAT. Es gab vier logische Geräte: con: für die Konsole (Tastatur und Bildschirm), lst: für den Drucker und RDR: und PUN: für einen Papierstreifenleser/stanzer (Lesen/Schreiben getrennt) . Der Papierstreifenleser war nur in den Anfangszeiten von CP/M als Gerät vorhanden und wurden z.B. mit einer seriellen Schnittstelle verbunden.

Der Benutzer konnte dieses Systems der Ports, so hießen sie technisch, auf bis zu 16 ausweiten, so trennte CP/M 3.0 den Con: Port in zwei separate Ports für Eingabe und Ausgabe. Dazu war aber eine BIOS Anpassung nötig. Die meisten CP/M-Programme verwendeten daher nur die Standardports. Der Vorteil war, dass man so die physikalischen Ports den logischen Ports zuordnen konnte. Die Bildschirmausgabe eines Programms konnte auf den Drucker umgeleitet werden oder die Kommandoeingabe auf eine Batchdatei. Folgende physikalischen Geräte kannte CP/M:

 

Device Meaning
TTY: Teletype device (slow speed console)
CRT: Cathode ray tube device (high speed console)
BAT: Batch processing (console is current RDR:, output goes to current LST: device)
UC1: User-defined console
PTR: Paper tape reader (high speed reader)
UR1: User-defined reader #1
UR2: User-defined reader #2
PTP: Paper tape punch (high speed punch)
UP1: User-defined punch #1
UP2: User-defined punch #2
LPT: Line printer
UL1: User-defined list device #1

CP/M Rechner heuteIn der Praxis war natürlich wichtig, welche Hardware verbaut war. PTR und PTP wurden, als Bezeichnung von der UR-CP/M Version übernommen, aber wenige Jahre später, als kein Papierstreifenleser/-stanzer mehr im Einsatz war, z.B. der seriellen Schnittstelle zugeordnet. Die User Definied Geräte erforderten eine BIOS-Anpassung. TTY war trotz des Namens immer die Tastatur des Computers. Mittels Stat dev: konnte man die Belegung anzeigen:

A>stat dev:

CON: is TTY:

RDR: is PTR:

PUN: is PTP:

LST: is LPT:

und so konnte man eine Belegung ändern:

A>stat con:=crt:

Vielfalt und riesige Programmauswahl

CP/M ermöglichte zwei Dinge. Es war zum einen ein Standard und zum anderen lies es dem Hersteller Freiheiten. Es war ein Standard, weil jedes Programm das auf eine Anfangsadresse von 100H compiliert oder assembliert ist und nur die BDOS oder BIOS Funktionen nutzt auf jedem Rechner bei dem CP/M läuft nutzbar ist.

Ein Newcomer im Computerbereich hat üblicherweise das Problem, das wenn er ein eigenes Betriebssystem einsetzt es dafür keine Software gibt, was sowohl für Käufer wie Softwareentwickler ein großes Manko ist. CP/M machte Programme austauschbar. Ein Redakteur der Zeitschrift ct’ schrieb, das Wordstar die Killerapplikation für CP/M war. Damit konnte man Texte schreiben, ähnlich wie später unter Word für DOS – es war schwerer zu bedienen, aber die meisten Funktionen hatte es schon.

Auf der anderen Seite machte CP/M kaum Hardwarevorschriften – eigentlich nur den Prozessor. Es lief auf jedem 8080, 8085 oder Z80 Prozessor (später würde man dies durch den HD64180, Z180 und EZ80 ergänzen). Als Extreme gab es Laptops mit CMOS-Stromspar CPUs und Rechner mit Z80B/C mit 6 bis 8 MHZ Takt. Es gab Rechner mit einfachem Textbildschirm, andere hatten auch die Fähigkeiten Schriftstile wie Fett oder Kursiv darzustellen. Mein Rechner setzte sogar einen Grafikbildschirm ein. Wie viele Zeilen der Bildschirm hatte, war egal, ebenso die Breite, nur 64 Zeichen mussten es mindestens sein. Ebenso konnte man ein 8 Zoll, 5,25, 3,5 oder 3 Zoll Laufwerk oder sogar eine Festplatte einsetzen. Anzahl der Sektoren, deren Größe, Spurzahl und Dichte waren variabel. Formatierte Kapazitäten von Disketten lagen den auch zwischen 90 und 800 KByte und es gab über 100 Diskettenformate.

Das war zu dieser Zeit einmalig. Wer einen Heimcomputer kaufte, konnte keine Software austauschen. Die Ataris, Apple II und Commodore VC20 / C64 hatten alle einen 65092 Prozessor, aber die Software des einen lief nicht auf dem anderen. Ja selbst innerhalb eines Herstellers waren Rechner inkompatibel, so lief auf einem C64 nicht BASIC-Programme seines Vorgängers VC20 ohne Anpassung, geschweige denn das man nicht den Quelltext, sondern wie bei CP/M das ausführbare Binärfile startet.

Nicht einmal UNIX das es damals gab und das entwickelt wurde damit es auf vielen Rechnerarchitekturen lief war soweit. Man konnte auf einem neuen Rechner Unix aus den Quellen übersetzen, musste es aber in der Regel anpassen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden.