Das ST-Betriebssystem Teil 2

In dem ersten Teil unserer Serie über das Betriebssystem des Atari-ST wurde über die allgemeine Ausgabe eines Betriebssystems berichtet. Ebenso wurde über die Unterteilung des TOS in einem Hardware-unabhängigen Teil (GEM-DOS genannt) und einem Hardwareabhängigen Teil (BIOS und XBIOS) gesprochen.

Wir haben einen Teil der wichtigen Routinen des GEMDOS in unserem ersten Teil schon behandelt Diesmal möchten wir mit der GEMDOS Routine fortfahren.

Wegen eines Fehlers bei der Zusammenstellung unserer Zeitung wurde die Tabelle aller 51 Routinen der GEMDOS nicht als Tabelle gedruckt, sondern als fortlaufender Text, der natürlicherweise Verwirrung stiftete. Deswegen sehen Sie noch einmal in Bild 1 alle 51 Routinen abgebildet.

SET DATA
	MOVE.L # PUFFER, — (SP) ;Adresse 44-Byte Puffer 
	MOVE.W #$1A,	—	(SP)	.-Funktionsnummer
	TRAP	#1	;GEMDOS Aufrufen
	ADDQ.L #6,SP	;Stack Korrektur

$1A SET DTA

Durch Set Disk Transfer wird die Adresse eines 44 Byte langen Puffers festgelegt, die für verschiedene Disketten-Operationen nötig ist.

$20 SUPER

Diese Funktion steht in enger Beziehung zu einem wichtigen Merkmal des 68 000 Mikroprozessors. Der 68 000 CPU kann in zwei Ebenen arbeiten: der sogenannten USER-Ebene und die SUPERVISOR-EBENE. Es gibt bei dem Befehlsvorrat dieses CPU’s eine Anzahl an Befehlen (Privilegierte), die nur in SUPERVISOR-Modus zu erreichen sind. Durch das S-Bit im Status-Register wird bestimmt, ob der Mikroprozessor sich in dem einen oder anderen Modus befindet. Bei dem Atari-ST gelingt es durch die Funktion SUPER, den SUPERVISOR-Modus zu erreichen. Diese Funktion ist für Programmierer, die Peripheriebausteine oder die Systemvariablen manipulieren wollen, unerläßlich. Alle diese Adressen sind sozusagen „geschützt“ und nur in SUPERVISOR-Modus erreichbar. Wir werden im Anhang ein Beispiel für die Wirkung dieser Funktion demonstrieren. Es gibt bei den Systemvariablen, bei Adresse $4EE, einen Flag, der für die Bildschirm-Hardcopy verantwortlich ist. Wird ALT und HELP gedruckt, so wird der Inhalt von $4EE um 1 inkrementiert und eine Hardcopy aufgelöst. In unserem Beispiel tun wir nichts anderes. Nachdem wir in SUPERVISOR-Modus gelandet sind, verändern wir den Inhalt dieser Systemvariablen und verursachen damit eine Hardcopy des Bildschirms.

Die GEMDOS Funktionen	$30	GEMDOS NUMBER
$00 TERM	$31	KEEP PROCESS
$01 CONIN	$36	GET DISK FREE SPACE
$02	CONOUT	$39	MKDIR
$03	AUXIN	
$04	AUXOUT		$3A RMDIR
$03	PRINTOUT	$3B CHDIR
$06	RAWCONIO 	$3C CREATE
$07 CONIN WITHOUT ECHO $3D OPEN 
$08	GONIN WITHOUT ECHO $3E CLOSE
$09	PLINE		$3E	READ
$0A	READLINE	$40	WRITE
$0B	CONSTAT		$41 UNLINK
$0E	SETDRV		$42	LSEEK
$10	CONOUT STAT	$43	CHANGE MODE
$11	PRTOUT STAT	$45 DUP
$12	AUXINSTAT	$46 FORCE
$13	AUXOUT STAT	$47 GETDIR
$19	CURRENT DISK	$49 MFREE
$1A	SET DTA		$4A	SETBLOCK
$20	SUPER		$4B	EXEC
$2A	GET DATE	$4C	TERM
$2B	SET DATE	$4E	SFIRST
$2C	GET TIME	$4F	SNEXT
$2D	SET TIME	$5b	RENAME
$2F	GET DTA		$57	GSDTOF


SUPER CLR.L	-(SP)
	MOVE.W #$20,-(SP) ;Funktionsnummer 
	TRAP # 1	;GEMDOS Aufrufen
	ADDQ.L #6,SP ;Stack Korrektur 
	MOVE.L D0,A2 ;Stack merken 
	MOVE.L #$1,$4EE	;1 in $4EE
	MOVE.L A2,-(SP) ;Alten Wert in SP 
	MOVE.W #$20,-(SP)
	TRAP #1
	ADDQ.L #6,SP
	CLR	-(SP)
	TRAP #1 END

$2A GET DATE

Durch diese Funktion läßt sich das eingestellte Datum auf dem Kontrollfeld ermitteln. Nach Aufruf von GET DATE steht das Datum in dem LOW-WORD des Registers DO. Allerdings ist das Datum in eine kodierte Form gepackt, so daß diese noch verarbeitet werden müssen.

LOW-WORD Register DO

Bit 0—4 = Tag
Bit 5-8 = Monat
Bit 9-15 = Jahr + 1980

GET DATE
	MOVE.W #$2A, — (SP) ;Funktionsnummer 
	TRAP #1	;GEMDOS aufrufen
	ADDQ.L #2, SP	;Stack Korrektur

Inhalt von Register DO:

DO = 00000C78

$2B SET DATE

SET DATE bildet das Gegenstück der oben beschriebenen Funktion. Dadurch läßt sich das Datum einstellen. Eine solche Funktion ist interessant für Anwenderprogramme, zu denen das Datum mit zum Protokoll gehört. Insofern kann man eine Routine einbauen, in der der Anwender gefordert wird, das aktuelle Datum einzugeben. Das Datum wird der Funktion SET DATE in ein Word übergeben in folgendem Format:

Bit 0—4 = Tag
Bit 5-8 = Monat
Bit 9-15 = Jahr - 1980

SET DATE
	MOVE.W #%0001001010011000, - (SP) 
	MOVE.W #$2B, - (SP)
	TRAP #1 ADDQ.L #6,SP

0001001010011000 entspricht 24.4.1989 #%0001001010011000 = $1298

$2C GET TIME

Die Funktion GET TIME verhält sich analog zu GET DATE, aber es wird bei dem Aufruf die Uhrzeit geliefert. Nach Ausführung von GET TIME steht in LOW-Word des Registers DO die aktuelle Uhrzeit zur Verfügung. Das Uhrzeit-Format sieht folgendermaßen aus:

Bit 0—4 = Sekunden (muß mit 2 multipliziert werden)
Bit 5-10 = Minuten
Bit 11-15 = Stunden (24h Format)

GET TIME
	MOVE.W #$2C, - (SP) 
	TRAP #1 
	ADDQ.L #2,SP

Inhalt von Register DO :

DO = 00001A16 entspricht 3,23

$2D SET TIME

Dadurch läßt sich die Uhrzeit einstellen. Die gewünschte Uhrzeit wird als Wort-Länge auf dem Stack übergeben. Das Format sieht genauso aus wie bei GET TIME.

Bit 0-4 = Sekunden
Bit 5—10 = Minuten
Bit 11-15 = Stunden

SET TIME
	MOVE.W #%0001101010101001, -(SP) 
	MOVE.W #$2D, - (SP)
	TRAP #1 
	ADDQ.L #6,SP

00011010101010011 entspricht 3,22

$2F GET DATA

Die Funktion GET DATA ist das Gegenteil der Funktion SET DATA. Nach Aufruf dieser Funktion wird die momentane Adresse eines Puffers für Disketten-Daten-Transfer im Register DO übergeben.

GET DATA
	MOVE.W #$2F, - (SP)
	TRAP #1 
	ADDQ.L #2,SP

Inhalt von Register DO :

DO = 000ADA52

$30 GET VERSION-NUMBER

Nach Ausführung von GETVNUMBER erhält man im LOW-WORD des Registers DO die derzeitige Versions-Nummer des GEMDOS.

GET VERSION-NUMBER
	MOVE.W #$30, - (SP)
	TRAP #1 ADDQ.L #2,SP

Inhalt von Register DO :

DO = 00001300

$31 KEEP PROCESS

Diese Funktion verhält sich ähnlich wie der in unserer letzten Ausgabe beschriebenen Funktion TERM. Auch hier wird nach Ausführung von KEEP PROCESS das laufende Programm beendet und kehrt zurück an das Programm, von dem aus es gestartet wurde.

Zwischen KEEP PROCESS und TERM gibt es einige Unterschiede. Einer davon ist die sogenannte Abschlußbedingung. TERM liefert immer den Abschlußwert 0, der signalisiert, daß kein Fehler vorhanden ist. KEEP PROCESS Kann einen Wen zwischen 0 oder 1 annehmen, wobei 0 „kein Fehler“ bedeutet und 1 das Gegenteil darstellt.

Ein anderer, schwerwiegender Unterschied liegt bei der Speicherverwaltung. Wird ein Programm durch TERM beendet, so wird der gesamte Speicher freigegeben und mit Nullen gefüllt. Mit der Funktion KEEP PROCESS darf man einen bestimmten Speicherbereich schützen. Die Anzahl von Speicherplätzen wird in den Stack übergeben.

KEEP PROCESS
	MOVE.W #0, - (SP) 
	MOVE.L #$200,-(SP) 
	MOVE.W #$31, -(SP) 
	TRAP #1

$36 GET DISK FREE SPACE

Hierdurch kann der Anwender die Größe der freien Plätze auf der Diskette er- I fahren. Für Programme, die ständig Daten auf Diskette ablegen, ist das von sehr großer Bedeutung, denn es wird ein möglicher Datenverlust vermieden. Diese Funktion benötigt mehrere Parameter, die alle nacheinander auf den Stack übergeben werden müssen. Der erste Parameter ist die Nummer des aktiven Laufwerkes. Der nächste Parameter ist die Adresse eines 16 Byte großen Puffers. Der letzte ist die Funktionsnummer selbst. Die gewonnene Information wird in dem oben genannten Puffer abgelegt. In dem ersten LONG-WORD dieses Puffers liegt die Anzahl der noch freien Allocation Unites. Das zweite Long Word beinhaltet die Menge der totalen Allocation Units. Das dritte enthält die Größe eines Sectors in Byte (512 Byte). In dem letzten Long-Word steht die Anzahl von Sectoren, die zu jedem Allocation Unit gehören.

	GET DISK FREE SPACE
PUFFER ;
	BLK.B 16
	MOVE.W #01, - (SP)
	MOVE.L # PUFFER, - (SP) 
	MOVE.W #$36, - (SP)
	TRAP #1 
	ADDQ.L #8,SP
	CLR - (SP)
	END.

$39 MKDIR

Mit Hilfe dieser Funktion lassen sich auf eine sehr einfache Art und Weise sogenannte Ordner anlegen. Um einen neuen Ordner anzulegen, muß man die Adresse, in dem sich der Name des Un-terdirectorys befindet, in den Stack übergeben. Der Name darf acht Zeichen lang sein und die Extension drei Zeichen lang. Der Ordnername muß mit einem Null-Byte abgeschlossen sein. Ob die Funktion erfolgreich druchgeführt wurde, wird im Register DO mitgeteilt. Eine Null bedeutet eine gelungene Ausführung und eine negative Zahl stellt eine fehlerhaft ausgeführte Funktion dar.

	MKDIR
ORDNAME:
	DC.L ”ST-COM.DAT”,0
	MOVE.L # ORDNAME, - (SP)  
	MOVE.W #$39, - (SP)
	TRAP #1 ADDQ.L #6,SP

$3A RMDIR

Ein leeres Subdirectory läßt sich mit der Funktion RMDIR löschen. Wie zuvor bei der MKDIR-Funktion wird auch hier der sogenannte Pfadname in den Stack abgegeben und dann die Funktion aufgerufen. Der Erfolg oder Mißerfolg der Durchführung wird im Register DO signalisiert.

	RMDIR
ORDNAME:
	DC.L ”ST-COM.DAT”,0
	MOVE.L # ORDNAME, - (SP)  
	MOVE.W #$3A,-SP 
	TRAP #1 
	ADDQ.L #6,SP

$3D CHDIR

Um eine bessere Datenorganisation zu erhalten, kann man bei einem Ordner einen Unterordner anlegen. Das kann man noch weiter fortsetzen (bedeutet: daß bei dem zweiten Unterordner wieder ein Ordner angelegt werden kann). Möchte man einen bestimmten File von diesem Subdirectory einladen, muß man den ganzen Pfadnamen als Argument eingeben.

Beispiel:

Zeitung . dat / Fachz. dat /
	C-Zeitung. dat / ST-Z. dat

Das läßt sich folgendermaßen erklären: Lade den File ST-Z aus dem Subdirectory C-Zeitung, der sich seinerseits in dem Subdirectory-Fach befindet und der zu dem Ordner „Zeitung“ gehört. Um die ganze Prozedur bei erneutem Laden von einem anderen File zu vermeiden, kann man durch die Funktion CHDIR einen Subdirectory zum aktuellen Directory machen. Dann sieht der Aufruf folgendermaßen aus:

	CHDIR
NAME:
DC.L ”/ZEITUNG.DAT/ST-Z.DAT/”,0 
MOVE.L #NAME, - (SP)
MOVE.W #$38, - (SP)
TRAP	# 1
ADDQ.L #6,SP

$3C CREATE

Um überhaupt mit der Datei etwas anfangen zu können (lesen, schreiben usw.) muß diese Datei zuerst vorhanden sein. Mit der Funktion CREATE wird eine kreiert. CREATE verlangt zwei Parameter: Erstens ein sogenanntes Attribut und zweitens die Adresse, in der sich der File-Name befindet.

Attribut

0 = Datei kann beschrieben oder gelesen werden
1 = Datei kann nur gelesen werden
2 = Datei ist eine „Versteckte Datei“
4 = Datei ist eine „Versteckte System-Datei“
8 = erzeugt ein sogenanntes Volumen-Label

Nach der Ausführung von CREATE wird im Regisdter DO ein File-Deskriptor zurückgegeben. Dieser File-Deskriptor ist für weitere Zugriffe auf der Datei von Bedeutung. Wenn sich bei Aufruf dieser Funktion eine gleichnamige Datei auf der Diskette befindet, so wird diese auf Null-Länge reduziert, in einem Wort, gelöscht und von der neuen Datei ersetzt.

	CREATE
NAME:
	DC.L ”ST-COM.DAT”,0
FILED:
	BLK.W 1
MOVE.W # 1, - (SP)
MOVE.L # NAME, - (SP) 
MOVE.W #$3C, - (SP)
TRAP #1 
ADDQ.L #8,SP 
MOVE.W DO,# FILED

$3D OPEN

Um mit der Datei weiter arbeiten zu können, muß sie zuerst geöffnet werden. Auch diese Funktion benötigt zwei Parameter. Der erste Parameter signalisiert den arbeitenden Modus. Der zweite zeigt die Adresse, in dem sich der File-Name befindet. Dieser muß, wie schon bekannt, mit einem Null-Byte abgeschlossen sein.

Arbeits-Modus

0 = Datei kann nur gelesen werden
1 = Datei kann nur beschrieben werden
2 = Datei kann wahlweise gelesen oder beschrieben werden

Auch hier wird der schon bekannte File-Deskriptor ins Register DO übergeben.

	OPEN
NAME:
	DC.L "TEST.DAT”,0
F1LED:
	BLK.W 1 
	MOVE.W #$2, - (SP)
	MOVE.L #NAME, - (SP) 
	MOVE.W #$3D, - (SP)
	TRAP #1 
	ADDQ.L #8,SP 
	MOVE.W DO,# FILED

$3E CLOSE

Wenn aus einer Datei nicht mehr zugegriffen wird oder das Arbeiten mit dem Programm beendet ist, sollte eine geöffnete Datei wieder abgeschlossen werden. Vor allem bei Dateien, in denen es sich um „Schreiben“ handelt, muß, um Dateiverluste zu vermeiden, ordnungsgemäß abgeschlossen werden. Die Funktion CLOSE verlangt, daß die File-Deskriptor-Nummer als Parameter ins Stack übergeben werden sollte. Eine ordnungsgemäß geschlossene Datei erkennt man an dem Wert Null im Register DO.

	CLOSE
FILED:
	BLK.W 1
	MOVE.W # FILED, - (SP)
	MOVE.W #$3E, - (SP)
	TRAP #1
	ADDQ.L #4,SP

$3F READ

Um Daten auf eine vorhandene Datei zu lesen, bedient man sich der Funktion READ. READ wird mit drei Parametern versorgt: Erstens die Adresse eines Puffers, in dem die Daten abgelegt werden sollten, zweitens die Anzahl der zu lesenden Bytes. Der dritte und letzte Parameter beinhaltet die File-Deskriptor-Nummer, die durch die Funktion OPEN ermittelt wurde. Wenn die Operation fehlerfrei gelaufen ist, steht im Register die Anzahl der gelesenen Bytes.

	READ
FILNAME:
	DC.L ’’TEST.DAT”,0
FILED:
	BLK.W 1
PUFFER:
	BLK.B #256
	MOVE.W #$02, - (SP)
	MOVE.L # FILNAME, - (SP) 
	MOVE.W #$3D, - (SP)
	TRAP #1 
	ADDQ.L #8,SP 
	MOVE.W DO,# FILED
	MOVE.L # PUFFER, - (SP) 
	MOVE.L #256, - (SP)
	MOVE.W # FILED, - (SP) 
	MOVE.W #$3F, - (SP)
	TRAP #1 
	ADD.L # 12,SP

$40 WRITE

WRITE beschreibt das Gegenstück der oben beschriebenen Funktion. Auch hier werden drei Parameter benötigt. Die Parameterbeschreibung entspricht ungefähr der bei der READ-Funktion. Im Puffer befinden sich allerdings die Daten, die geschrieben werden müssen.

Die Ausgabe muß nicht unbedingt auf einem Laufwerk geschehen (Datei), sondern bei Änderungen der File-Deskriptor-Nummer kann auf den Bildschirm, Drucker usw. umgeleitet werden.

Andere File-Deskriptor-Nummern:

0 = Konsole — Eingabe
1 = Konsole - Ausgabe
2 = RS 232
3 = Drucker

	WRITE
FILNAME:
	DC.L ”TEST.DAT”,0
FILED:
	BLK.W 1
	MOVE.W #$02, - (SP)
	MOVE.L # FILNAME, - (SP) 
	MOVE.W #$3D, - (SP)
	TRAP #1 
	ADDQ.L #8,SP 
	MOVE.W DO,# FILED
	MOVE.L #PUFFER, - (SP) 
	MOVE.L #256, - (SP)
	MOVE.W # FILED, - (SP) 
	MOVE.W #$40, - (SP)
	TRAP #1 
	ADD.L # 12,SP

$41 UNLINK

Mit dieser Funktion können überflüssige Dateien gelöscht werden. Die Adresse, in der sich der File-Name befindet, wird in den Stack abgelegt. Bei erfolgreicher Löschung der Datei enthält das Register DO eine Null. Ein Wert ungleich Null signalisiert eine fehlerhafte Ausführung.

	UNLINK
FILNAME:
	DC.L ”TEST.DAT”,0
	MOVE.L # FILNAME, - (SP) 
	MOVE.W #$41, - (SP)
	TRAP #1 
	ADDQ.L #6,SP

Fortsetzung folgt.



Aus: ST-Computer 05 / 1986, Seite 49

Links

Copyright-Bestimmungen: siehe Über diese Seite