Systemnahe
Programmierung

E-Books


MS-DOS Kurs


3. Unterstützung durch Hochsprachen

Bei der Nutzung von systemnahen Funktionen in den Hochsprachen befindet man sich in einem einzigen Dilemma: Selbstverständlich bieten alle Compiler inzwischen umfangreiche und kompfortable Funktionen an, die aber allerhöchstens zu sich selbst kompatibel sind. Mag man sich noch damit abfinden, daß eine Portierung auf andere Betriebssysteme nicht in Frage kommt und jede Version Änderungen bringt, so ist es schon ärgerlich, daß sich auch Compiler gleicher Sprachen in den systemnahen Funktionen so unterscheiden, daß man stets an die Spezifika seines Compilers gebunden bleibt. Quick and Dirty ist also auch für den Programmierer angesagt, wenn er nicht auf jegliche systemnahen Funktionen verzichten will - aber dann macht DOS auch kaum noch die Hälfte Spaß.
Ein bereits angesprochenes Problem wäre die Abfrage einer Enviroment-Variablen, weil dort ein Pfad oder ein Paßword gespeichert ist. Turbo-Pascal kennt für die Enviroment-Behandlung drei Funktionen, zur Ermittlung der Parameterzahl, der n-ten Varibalen und einer bestimmten Variablen. Letztere käme uns entgegen, um ein Paßwort zu prüfen.

USES dos;
VAR Password: STRING[79];

BEGIN
    Password:=GetEnv('Pass');
    IF Password='alles roger' THEN {OK}
    ELSE Write('Ha ha ha');
END.

Das Programm läuft nur dann in den OK-Zweig, wenn zuvor auf Kommandoebene mit
set Pass = alles roger
eine Umgebungsvariable gesetzt wurde.
Auf diese Weise kann ein Programmpfad oder eine Variable zur Konfiguration abgefragt werden. Entsprechende Konstukte sind auch in anderen Programmiersprachen zu finden; die Ausgabe des gesamten Enviroments sähe in Microsoft C folgendermaßen aus:

#include <stdio.h>
#include <stdli.h>
#include <dos.h>

main()
{ while(*environ!=NULL)
printf("%s\n",*environ++);}

Auch in Basic ist so etwas kein Problem, wobei hier in besonderem Maße gilt, was vorher bereits für die anderen Sprachen gesagt wurde: Die Dialekte unterscheiden sich stark.
Trotz der guten Unterstützung in Hochsprachen bleiben einige Operationen scheinbar umständlich, einfach deshalb, weil die Funktionalität des Betriebssystems direkt abgebildet wird. Schauen wir uns nur einmal die Anzeige des aktuellen Verzeichnisses an. Das Betriebssystem benötigt dazu intern zwei Funktionen, und so werden sie auch in Turbo-Pascal durchgereicht. Zuerst wird der erste Eintrag gesucht (FindFirst), der einer vorgegebenen Maske entspricht (Angabe von Jokern), anschließend wird mit einer anderen Funktion (FindNext) solange der jeweils nächste Eintrag geholt, bis keiner mehr vorhanden ist. Die Ausgabe auf den Bildschirm sieht als Pascal-Sequenz folgendermaßen aus:

USES dos;
VAR DirInfo: SEARCHREC;

BEGIN
    FindFirst('*.PAS',Archive,DirInfo);
    WHILE DosError=0 DO BEGIN
       Writeln(DirInfo.Name);
       FindNext(DirInfo);
    END;
    Read;
END.

Das scheinbar umständliche Vorgehen bekommt aber dann Sinn, wenn das Verzeichnis nicht einfach nur ausgegeben, sondern in eine Liste gespeichert werden soll, da vorher nicht zu ermitteln ist, wieviele Einträge sich in einem Verzeichnis befinden. Vor das Problem der Verwaltung aller Verzeichniseinträge wird man gestellt, wenn man eine ansprechende Oberfläche gestalten muß, also das Verzeichnis in ein Fenster ausgibt oder den Nutzer einer Datei aus eine Pick-Liste auswählen will. Eine andere Funktion, die ein vorausschauender Progammierer durchaus benötigt, ist die Ermittlung des freien Speichers auf einem Datenträger, was in Hochsprachen kein Problem ist:

USES dos;

BEGIN
    Writeln(DiskFree(3) DIV 1024,' KByte frei auf Laufwerk C:');
END.

Später werden wir uns ansehen, wie man sich diese Funktion selbst schreiben kann. In der Tafel 1 sind die Funktionen der Unit DOS von Turbo-Pascal zusammengefaßt, die die meisten systemnahen Arbeiten abdeckt. Einige Funktionen sind auch in anderen Units enthalten, etwa Sound in Crt. Die Tonausgabe wird vom Betriebssystem überhaupt nicht unterstützt, so daß man auf direkte Portausgänge zurückgreifen müßte, wenn der Compiler so etwas nicht anbieten würde. So aber lassen sich einfach Töne einer bestimmten Frequenz ausgeben, die so lange gehalten werden, bis NoSound sie wieder abschaltet.
So würde
Sound(880);
einen Kammerton A erzeugen.
Je nach Rechner hört sich die Ausgabe etwas verschieden, aber sicher nicht zufriedenstellend an. Für ein kleines DingDong statt eines aufdringlichen Piepsens sollte es aber ausreichen.


Tafel 1 Funktionen der Unit DOS von Turbo-Pascal 6.0
Funktion Aufgabe
DiskFree Ermitteln des freien Speichers eines Laufwerkes
DiskSize Ermitteln Gesamtkapazität eines Laufwerkes
DosExitCode Ermitteln des Rückkehrcodes eines untergeordneten Programms
DosVersion Ermitteln der DOS-Version
EnvCount Ermitteln der Anzahl von Enviroment-Variablen
EnvStr Ermitteln der n-ten Enviroment-Variablen
Exec Ausführen eines DOS-Programms
FExpand Erweitern eines kurzen Filenamens zum vollständigen aktuellen Pfad
FindFirst Ermitteln des ersten Verzeichnis-Eintrages
FindNext Ermitteln des nächsten Verzeichnis-Eintrages
FSearch Suche einer spezifizierten Datei
FSplit Zerlegen eines vollständig angegebenen Pfadnamens in seine Komponeneten
GetCBreak Ermitteln, bei welchen Operationen DOS auf <CTRL><BREAK> bzw. <STRG><UNTBR> prüft
GetDate Ermitteln des aktuellen Systemdatums
GetEnv Ermitteln einer Enviroment-Variablenbelegung
GetFAttr Ermitteln der Attribute einer Datei
GetFTime Ermitteln von Datum und Uhrzeit der letzen Änderung einer Datei
GetIntVec Ermitteln eines Interrupt-Vektors
GetTime Ermitteln der aktuellen Systemzeit
GetVerify Ermitteln des DOS-Verify-Flags
Intr Aufruf eines Software-Interrupts
Keep Beenden der Initialisierung eines im Hintergrund weiterarbeitenden (residenten) Programms
MsDos Aufruf des Interrupts 21H (DOS-Sammel-Interrupt)
PackTime Konvertieren von Datum und Zeit in eine LONGINT, wie er von SetFTime verwendet wird
SetCBreak Setzen des Break-Flags von DOS
SetDate Setzen des Systemdatums
SetFAttr Setzen des Dateiattributes
SetFTime Setzen von Datum und Zeit einer Datei
SetIntVec Setzen eines Interruptvektors auf eine eigene Adresse
SetTime Setzen der Systemzeit
SetVerify Setzen des Verify-Flags
SwapVectors Vertauschen der Interruptvektoren des Systems mit denen der Unit
UnpackTime Konvertieren von Datum und Zeit aus einem LONGINT von GetFTime in Datum und Zeit


(c) Jürgen Richter