Anhang E - Glossar
API ist die Abkürzung für "Application Program Interface"
und stellt eine spezifische, klar definierte Funktionsschnittstelle für
Programme dar. Diese Programme können über diese Schnittstelle
Dienste des jeweiligen Laufzeitsystems in Anspruch nehmen, auf das sich
das API bezieht. So gibt es z.B. ein DOS-API, ein BIOS-API, ein Windows-API
etc.
Bibliothek, dynamisch (DLL)
Eine dynamische Bibliothek stellt eine Ansammlung von Funktionen dar,
auf die Applikationen zugreifen können. Sie ist mit einer Programmdatei
vergleichbar, besitzt aber keinen eigenen Stack und keinen Einstiegspunkt
zur Ausführung. Beim Linken einer Applikation werden in die Programmdatei
nur Querverweise auf die entsprechenden Funktionen in den DLLs hinterlegt.
Die "dynamische Bindung" zwischen Programm und DLL wird durch den Programmlader
beim Start der Applikation vorgenommen, der mit den Querverweisen aus
der Programmdatei die entsprechende DLL einlädt und danach die Adressen
der Funktionen in der DLL ermitteln kann. DLLs können ebenso wie Applikationen
auf Funktionen in anderen DLLs zugreifen, da sie (wie oben erwähnt)
vom Programmlader praktisch wie Programmdateien behandelt werden. Im Gegensatz
zur statischen Bindung von Funktionen steigt die Größe einer
Programmdatei bei Verwendung der dynamischen Bindung nur unwesentlich.
Eine statische Bibliothek stellt eine Ansammlung von Funktionen und
Variablen dar, auf die Applikationen zugreifen können. Sie besteht
aus einer Reihe von Objektmodulen, die beim
Linken fest in eine Programmdatei integriert werden ("statische Bindung").
Je mehr Objektmodule eine Applikation benötigt, desto größer
wird auch die eigentliche Programmdatei. Neben den eigentlichen Objektmodulen
enthalten statische Bibliotheken ein Verzeichnis mit allen öffentlichen Symbolen
und pro Symbol einen Verweis auf das jeweilige Objektmodul. Die Verwaltung
einer statischen Bibliothek wird durch einen sogenannten Bibliotheken-Manager
übernommen (z.B. DLIB, TLIB oder LIB).
Das BIOS (="Basic Input-Output System") stellt grundlegende Funktionen
zur Verfügung, die ein Programm zur Kommunikation mit der PC-Hardware
benötigt. Die einzelnen Funktionen des BIOS sind über ein API
erreichbar, wodurch Programme von den spezifischen Eigenschaften der einzelnen
Hardware-Komponenten isoliert werden. Viele Funktionen von MS-DOS beispielsweise
basieren größtenteils auf BIOS-Funktionen und greifen dabei
nicht selbst auf die Hardware zu.
Ein Callback ist ein vom DPMI-Host zur Verfügung
gestellter Dienst, der es einem DPMI-Client
beispielsweise ermöglicht, aus einem Real Mode-Interrupt-Handler eine
Protected Mode-Routine aufzurufen. Dadurch kann z.B. die Steuerung der
Tastatur vom Real Mode in den Protected
Mode verlagert werden, ohne daß das Programm eigene, spezielle
Real Mode-Interrupt-Routinen einsetzen muß.
Die grundlegende Aufgabe eines DOS-Extenders ist es, ein Programm im
Protected Mode auszuführen und vor
jedem DOS- oder BIOS-Aufruf in den Real Mode
zu schalten und danach wieder in den Protected Mode zu wechseln. Nach dem
Start eines Programms, das unter einem DOS-Extender läuft, legt dieser
die nötigen Systemtabellen (Beschreibertabellen, Interrupttabellen,
PageTables etc.) an, schaltet den Prozessor in den Protected Mode und lädt
das auszuführende Programm in den erweiterten Speicher, um es danach
auszuführen. Nachdem das Programm gestartet wurde, agiert der DOS-Extender
nur noch im Hintergrund und bietet seine Dienste meist über spezielle
Funktionsschnittstellen (APIs) an.
Das DPMI ( = "DOS Protected Mode Interface") entstand bei Microsoft
während der Entwicklung von Windows 3.0 um die Ausführung von
Programmen im erweiterten Speicher zu ermöglichen. Es deckt darüber
hinaus alle Dienstleistungen ab, die Programme im Protected
Mode zur störungsfreien Ausführung neben anderen Protected
Mode-Programmen benötigen, z.B. zentrale Verwaltung der Beschreibertabellen,
des erweiterten und konventionellen Speichers, der Interrupts
und Exceptions und Kommunikation zwischen Real-
und Protected Mode-Routinen.
Ein DPMI-Client ist ein Programm, das die Dienste eines DPMI-Hosts
in Anspruch nimmt.
Ein DPMI-Host ist ein Programm, das einem potentiellen DPMI-Client
seine Dienste (über APIs) zur Verfügung
stellt. Praktisch alle populären Multitasking-Betriebssysteme wie Windows 3.x/95/NT und
OS/2 besitzen einen integrierten DPMI-Host. Manche Hersteller wie Borland oder Quarterdeck
bieten eigenständig lauffähige DPMI-Hosts für MS-DOS an, meist aber als
Bestandteil eines größeren Programmpakets wie z.B. Borland C++ oder QEMM.
EMS ( = "Expanded Memory Specification") ist das Ergebnis von Versuchen,
die Speicherbegrenzung im Real Mode von 1 MB
zu sprengen und auf zusätzlichen Speicher zugreifen zu können.
Ursprünglich befand sich dieser zusätzliche Speicher auf speziellen
Erweiterungskarten, der häppchenweise in reservierte Bereiche des
koventionellen Speichers eingeblendet wurde (über einen sogenannten
"Seitenrahmen" bzw. "Page Frame") und dann benutzt werden konnte. Heute
wird dazu der erweiterte Speicher über der 1MB-Grenze verwendet, der
weiterhin seitenweise in den konventionellen Speicher eingeblendet wird.
Dazu ist EMS mittlerweile eng mit dem VCPI verwachsen,
da das Einblenden der Speicherseiten auf 80386- und höheren CPUs über
virtuelle Speichertechniken erheblich beschleunigt wird. Diese umständliche
und auch extrem langsame Technik der Nutzung des erweiterten Speichers
ist (wenn überhaupt) nur für Real Mode-Programme interessant,
denn Programme im Protected Mode können
direkt auf den erweiterten Speicher zugreifen. Der bekannteste EMS- und
VCPI-Treiber ist wohl Microsofts EMM386.EXE.
Eine Exception stellt einen Ausnahme-Zustand des Prozessors dar. Dies
kann beispielweise durch eine Division durch Null oder durch den Zugriff
auf einen Speicherbereich hervorgerufen werden, auf den ein Programm keinen
Zugriff hat. Durch spezielle Exception-Handler kann ein Betriebssystem
diese Fehler abfangen und gegebenenfalls korrigieren oder das Programm,
das einen solchen verursacht hat, kontrolliert beenden.
Das Flat-Speichermodell nutzt einige spezielle Eigenschaften des Protected
Mode aus, um die Segmentierung effektiv auszuschalten. Dazu werden
zwei Segmentbeschreiber angelegt (ein
Code- und ein Datensegment) und mit einer Größe von 4G und der
Basisadresse Null initialisiert. Nachdem die entsprechenden Selektoren
der beiden Beschreiber in die Segmentregister geladen wurden, ist der Zugriff
auf den gesamten linearen Adressraum der CPU über reine 32Bit-Offsets
möglich, ohne sich je wieder über eine Segmentierung Gedanken
machen zu müssen. Da dies nur im 32Bit-Protected Mode möglich
ist, ist diese Technik erst ab 80386-Prozessoren anwendbar.
GDT
Die GDT (= Globale Deskriptor-Tabelle) stellt ein Array aus Segmentbeschreibern
dar, welche die Eigenschaften von Segmenten im Protected Mode definieren.
Die Tabelle wird über einen Segmentselektor
indiziert, wobei jeder Segmentbeschreiber jeweils 8 Bytes innerhalb der
GDT belegt. Der Unterschied zur LDT besteht darin,
daß in der GDT zumeist Beschreiber des Betriebssystems untergebracht
werden. Die Unterscheidung, ob sich ein Selektor auf die GDT oder die LDT
bezieht, wird über ein spezielles Bit im Selektor geregelt. Die Lage
und Größe der GDT im physischen Speicher wird im GDTR-Register
vermerkt, auf das nur mit Befehlen der Privilegstufe
0 zugegriffen werden kann. Eine normale Applikation hat daher im allgemeinen
keine Möglichkeit, direkt auf die Beschreiber in der GDT zuzugeifen.
Die IDT (= Interrupt-Deskriptor-Tabelle) ist das Protected Mode-Pendant zur Interrupt-Vektortabelle des Real Mode, die Ähnlichkeit mit dem Aufbau der LDT und GDT hat. Die IDT stellt ein Array aus 256 Code-Selektoren und Offsets dar, die jeweils den Handler für einen der 256 Interrupts darstellen. Die Interrupt-Nummer (0-255) dient dabei als Index in die IDT. Die einzelnen Code-Selektoren der Handler stellen wiederum einen Index in die GDT oder eine LDT dar, in denen sich die Segmentbeschreiber befinden. Die Lage und Größe der IDT im physischen Speicher wird im IDTR-Register vermerkt, auf das nur mit Befehlen der Privilegstufe 0 zugegriffen werden kann. Eine normale Applikation hat daher im allgemeinen keine Möglichkeit, direkt (wie im Real Mode) auf die Interrupt-Tabelle zuzugeifen.
Ein Interrupt verursacht die kurzzeitige Unterbrechung der Arbeit der
CPU und läßt sie auf ein Ereignis reagieren, z.B. den Empfang
eines Tastencodes von der Tastatur oder die Reaktion auf das Bewegen der
Maus. Neben diesen durch die Hardware ausgelösten Unterbrechungen
gibt es auch durch die Software ausgelöste Interrupts. Dies geschieht
im allgemeinen durch die Ausführung eines "INT"-Befehls (siehe auch
IDT).
LDT
Eine LDT (= Lokale Deskriptor-Tabelle) stellt ein Array aus Segmentbeschreibern
dar, welche die Eigenschaften von Segmenten im Protected Mode definieren.
Die Tabelle wird über einen Segmentselektor
indiziert, wobei jeder Segmentbeschreiber jeweils 8 Bytes innerhalb der
LDT belegt. Der Unterschied zur GDT besteht darin,
daß in einer LDT Beschreiber für eine (einzelne) Applikation
untergebracht sind. In Multitasking-Umgebungen ist es daher möglich,
für jede Applikation eine individuelle LDT bereitzustellen. Die Unterscheidung,
ob sich ein Selektor auf die GDT oder eine LDT bezieht, wird über
ein spezielles Bit im Selektor geregelt. Die Lage und Größe
der aktuellen LDT im physischen Speicher wird im LDTR-Register vermerkt,
auf das nur mit Befehlen der Privilegstufe
0 zugegriffen werden kann. Eine normale Applikation hat daher im allgemeinen
keine Möglichkeit, direkt auf die Beschreiber in der ihr zugeordneten
LDT zuzugeifen.
Ein Objektmodul stellt eine von einem Compiler oder Assembler generierte Datei dar, die einen übersetzten Quelltext in Maschinensprache enthält. In der Windows- und DOS-Welt werden das sogenannte "Object-Module-Format" (OMF) und das "Common Object File Format" (COFF) als Strukturen für Objektmodule verwendet. Aus diesen Objektmodulen werden vom Linker mit Hilfe von statischen und dynamischen Bibliotheken Programmdateien erzeugt.
Privilegstufe
Bei den Intel-Prozessoren ab dem 80286 wird zwischen den Priviliegstufen
0 (=Systemkern), 1 (=Systemdienste), 2 (=Systemerweiterungen) und 3 (=Applikationen)
unterschieden. Die Privilegstufe 0 besitzt die meisten Privilegien, während
bei 3 die niedrigsten Privilegien gelten. Die einzelnen Privilegstufen
sind in den Segmentbeschreibern und
den Selektoren fest verankert. Über
die Privilegstufe entscheidet die CPU, ob z.B. auf bestimmte Register (IDTR,
GDTR, LDTR) zugegriffen und bestimmte CPU-Befehle ausgeführt werden
dürfen. Es gilt ferner die Regel, daß jedes Programm neben seinen
eigenen auch die Selektoren eines mit
niedrigeren Privilegien laufenden Programmes benutzen darf (handelt es
sich dabei um Codesegmente, kommen allerdings noch einige weitere Sonderregeln
zum tragen). Bei der Verwendung eines Selektors mit höheren Privilegien
wird von der CPU jedoch sofort eine Exception
ausgelöst.
Der Protected Mode bietet gegenüber dem Real
Mode viele Vorteile, z.B. direkter Zugriff auf den erweiterten Speicher,
32Bit-Registerbreite, kompletter Speicherschutz, virtuelle Speicherverwaltung,
weitgehende Abschottung von Programmen bei Multitasking-Betriebssystemen,
Privilegstufen für einzelne Ausführungseinheiten (Programmodule)
und neue Befehle. Um den Prozessor in den Protected Mode zu schalten reicht
es prinzipiell, das unterste Bit im MSW (Maschinenstatuswort) des Prozessors
zu setzen (im allgemeinen hat dies aber einen Absturz des Systems zur Folge,
da vorher weitreichende Maßnahmen getroffen werden müssen, wie
z.B. das Anlegen einer GDT, LDT
und IDT). Viele installierte Speichermanager verhindern
dies jedoch, um Instabilitäten des Systems zu vermeiden (ein Umschalten
des Prozessors unter Windows wäre ohne diese Vorkehrungen katastrophal).
Für einen Programmierer ist der sichtbarste Unterschied zwischen Real-
und Protected Mode die Bedeutung von Segmentselektoren.
Der Real Mode definiert das ursprüngliche Prozessor-Design, das
mit dem 8086 eingeführt wurde. Der Begriff "Real Mode" wurde allerdings
erst mit dem 80286 eingeführt, um ihn vom Protected
Mode zu trennen, da sich beide Betriebsmodi grundsätzlich voneinander
unterscheiden. Im Real Mode ist ein Programm generell auf 16Bit-Register
und die ersten 1 MB des Speichers begrenzt. Im Gegensatz zum Protected
Mode stellt ein Segmentselektor eine direkte
Adresse im ersten MB des Speichers dar. Um eine Adresse im Speicher anzusprechen,
wird ein 16Bit-Segment mit 16 multipliziert und auf einen Offset addiert.
Eine Relokation ist eine vom Programmlader eines Betriebssystems vorgenommene
Anpassung zur Laufzeit, die von einem Linker nicht gemacht werden konnte,
d.h. eine Anpassung an Gegebenheiten, die erst beim Start eines Programms
bekannt sind. Ein Real Mode-Linker beispielsweise weiß nicht, in
welches Segment das von ihm erzeugte Programm später geladen wird,
d.h. er muß jeden direkten Zugriff auf ein Programm-Segment relativieren
und für den Programmlader eine Information in der Programmdatei hinterlegen,
die den Ort des Zugriffs angibt, an dem die Anpassung an die realen Gegebenheiten
vorgenommen werden muß (Relokationstabelle). Im Protected
Mode besteht ein ähnliches Problem aufgrund des Flat-Speichermodells
bei Offsets, da Segmente dort keine mehr Rolle spielen. Ein Linker für
das Flat-Speichermodell weiß daher nicht, an welchen Offset im linearen
Speicher die Programmdatei später durch den Programmlader geladen
wird. Deshalb muß auch er eine Relokationstabelle (aber in etwas
anderer Form als beim Real Mode-Linker) für den Programmlader in die
Datei schreiben, die jede Verwendung eines Offsets (!) im Programm relativiert.
Segmentbeschreiber
/ -deskriptor
Ein Segmentbeschreiber ist ein 8 Byte großer Bereich innerhalb
der GDT oder einer LDT. In diesen
8 Bytes sind die Eigenschaften eines Speichersegments hinterlegt, auf das
über einen Selektor zugegriffen werden
kann. Die hier definierten Eigenschaften umfassen die Startadresse des
Segments, die Länge und bestimmte Attribute (Code- oder Datensegment,
lesbar, beschreibbar, 16- oder 32-Bit-Adressierung und die Privilegstufe).
Segmentselektor
Ein Segmentselektor stellt im Real Mode eine
direkte, reale Adresse dar, die sich auf das untere MB des Speichers bezieht,
der im Real Mode direkt adressiert werden kann. Im Protected
Mode stellt ein Segmentselektor einen Index in die GDT
oder eine der LDTs dar, in der die exakten Eigenschaften
eines Segments definiert werden (= Segmentbeschreiber).
Stack
Der Stack (=Stapelspeicher) ist ein besonderer Speicherbereich, der für jede Applikation zwingend erforderlich ist, welche lokale Daten in Funktionen definiert oder Funktionen aufruft. Er ist im Prinzip eine Art temporärer Speicher, der von Funktionen und der CPU benutzt wird. Der Stack wird im Gegensatz zu den meisten anderen Speicherblöcken rückwärts, d.h. von "hinten nach vorne" aufgefüllt. Der Zugriff auf den Stack geschieht nach dem LIFO-Verfahren ("last in-first out"), d.h. es können immer nur die Daten ausgelesen werden, die momentan "oben" liegen (vergleichbar etwa mit einem Stapel Getränkekisten : es kann immer nur die oberste Kiste entfernt und auch immer nur auf die oberste eine neue gestellt werden).
VCPI (= "Virtual Control Program Interface") war der Vorgänger
von DPMI und regelt ebenfalls die
Koexistenz von Programmen im Protected Mode, allerdings auf wesentlich
rudimentärere Art. Die Inanspruchnahme von Diensten des VCPI-Servers
(analog dazu DPMI-Host) erfordert deshalb wesentlich
detailierteres Wissen des Programmierers über die Vorgänge im
Protected Mode. Im allgemeinen stellt ein VCPI-Server auch EMS
zur Verfügung (und umgekehrt).
Das XMS (= "Extended Memory Specification") definiert einen Standard zum Zugriff auf den erweiterten Speicher oberhalb der 1MB-Grenze für Programme, die im Real Mode ablaufen. Da der erweiterte Speicher nur im Protected Mode erreichbar ist, schalten die einzelnen Funktionen des XMS-Standards eigenständig in den Protected Mode und danach wieder zurück, ohne daß das eigentliche Programm davon etwas merkt. Der Nachteil dieser Methode ist, daß der Zugriff auf Bereiche im erweiterten Speicher über diesen Standard nur über ein (zeitaufwendiges) Kopieren zwischen einzelnen Blöcken im konventionellen Speicher, auf die das Programm zugreifen kann, und den Blöcken im erweiterten Speicher funktioniert. Man hat also auch über die XMS-Schnittstelle im Real Mode architekturbedingt keinen direkten Zugriff auf den erweiterten Speicher; dies bleibt ausschließlich dem Protected Mode vorbehalten. Der am meisten verbreitete XMS-Treiber ist HIMEM.SYS von Microsoft.