x86-Programmierung und -Betriebsarten (Teil 6)

25.02.2004 von Hans-Peter Messmer und Klaus Dembowski
Die sechsteilige Artikelserie behandelt die Speicheradressierung und die x86-Betriebsarten. Der letzte Teil widmet sich einer weiteren Altlast der x86-Prozessoren - dem mysteriösen Virtual-8086-Modus.

Mit dem 80386 wurde ein neuer Betriebsmodus eingeführt, der ähnlich wie der Protected Mode des 80286 zu allerlei Verwirrung und Mythisierungen führte.

Der Antrieb zur Implementierung des Virtual Modes lag in der ganz enormen Anzahl von Programmen für den PC unter MS-DOS, einem reinen Real-Mode-Betriebssystem. Auch der leistungsfähigste x86-Prozessor arbeitet unter MS-DOS stets im Real Mode und kann damit nur das erste der 4096 MByte des 32-Bit-Adressraums benutzen. Darüber hinaus werden weder die umfangreichen Schutzmechanismen des Protected Modes noch die Paging-Mechanismen ab dem 80386 benutzt. Der Virtual Mode soll nun einerseits den Betrieb unveränderter Real-Mode-Programme für den 8086 ermöglichen und andererseits die Schutzmechanismen des Protected Modes ausnutzen.

Das Besondere dabei ist, dass die virtuellen 8086-Tasks parallel zu anderen virtuellen Tasks ablaufen können, das heißt es findet ein Multitasking mit nicht multitasking-fähigen Programmen statt. 8086-Programme unter MS-DOS sind nicht multitasking-fähig, da DOS als Betriebssystem nicht reentrant ist: Wird eine DOS-Funktion durch einen Interrupt unterbrochen, der ebenfalls eine DOS-Funktion aufruft, so stürzt der PC häufig ab, da nach einem IRET der ursprüngliche Stack zerstört ist. Aus diesem Grund ist die Programmierung von residenten (TSR-) Programmen relativ schwierig. Mit Hilfe des Virtual Modes und Paging lassen sich diese Schwierigkeiten aber elegant umgehen. Den Virtual-8086-Mode nutzen zum Beispiel die DOS-Fenster von Windows oder OS/2 aus.

Serie: x86-Programmierung und -Betriebsarten

Teil 1

Code-/Datensegment, Befehlszähler und Stack

Teil 2

Adressierungsarten und Befehlsdekodierung sowie Real Mode

Teil 3

Interrupts und Exceptions

Teil 4

Der Protected Mode

Teil 5

Paging

Teil 6

Der Virtual-8086-Modus

Die Artikelserie basiert auf dem Kapitel 6 des "PC Hardwarebuch" von Addison-Wesley. In unserem Buch-Shop können Sie das über 1200 Seiten starke Kompendium bestellen oder als eBook downloaden.

Virtuelle Maschinen und Virtual-8086-Monitor

Im Virtual Mode bilden die Hardware der CPU und der Virtual-8086-Monitor eine so genannte virtuelle Maschine. Bei einem System mit Multitasking-Unterstützung, kann das System für jeden Task eine eigene virtuelle Maschine bilden. Da die virtuellen Maschinen ständig für kurze Zeit bedient werden, findet Multitasking statt. Damit können beispielsweise ein Compiler, der Drucker-Spooler und ein Editor parallel arbeiten. Windows 9x/NT und OS/2 machen sich solche virtuellen Maschinen auf der Basis des Virtual Modes zu Nutze, um Real-Mode-Programme in der DOS-Box parallel zu den richtigen Protected-Mode-Anwendungen ablaufen zu lassen.

Der Virtual-8086-Monitor ist ein Systemprogramm (typischerweise ein Teil des Betriebssystem-Kernels), das zur Erzeugung und Verwaltung der virtuellen 8086-Tasks dient (engl. to monitor, dt. überwachen). Dabei stellt die Hardware der CPU über ein TSS einen Satz virtueller Register sowie einen virtuellen Speicherbereich entsprechend dem ersten MByte des linearen Adressraums des Tasks zur Verfügung. Außerdem führt der Prozessor die Befehle aus, die diese Register und den Adressraum des Tasks betreffen. Aufgabe des Virtual-8086-Monitors ist es, die Schnittstellen der virtuellen Maschine beziehungsweise des virtuellen 8086-Tasks nach außen hin zu überwachen.

Die Schnittstellen werden von Interrupts, Exceptions und den I/O-Anweisungen gebildet, sie übernehmen also die Aufgabe der physikalischen Schnittstellen (zum Beispiel Steuerregister) in einem gewöhnlichen 8086-PC. Der Monitor stellt sicher, dass sich die virtuelle 8086-Maschine als eigenständiger Task in das weit umfangreichere 32-Bit-System im Protected Mode einfügt, ohne andere Tasks oder möglicherweise sogar das Betriebssystem selbst zu stören.

Adressen im Virtual-8086-Mode

Auf den ersten Blick besteht der wesentlichste Unterschied zwischen Real und Protected Mode in der Art der Adressberechnung. Im Real Mode wird einfach der Wert des Segmentregisters mit 16 multipliziert. Im Protected Mode dient das Segmentregister dagegen als Index in eine Tabelle, in der die "richtigen" Adressen der Segmente stehen. Dadurch ist es zum Beispiel völlig unmöglich, aus einem Segment- und Offsetregisterwert unmittelbar auf die lineare Adresse des Objekts zu schließen. Genau dies praktizieren jedoch viele alte Real-Mode-Programme, eine ordnungsgemäße Ausführung im Protected Mode ist dadurch unmöglich.

Soll der 32-Bit-Prozessor nun im Virtual Mode die Ausführung von 8086-Programmen ermöglichen, so muss er die Adresse wie der 8086 im Real Mode berechnen. Im Virtual-8086-Mode erzeugt der Prozessor also die Adresse, indem er den Wert des Segmentregisters mit 16 multipliziert und den Offset hinzuaddiert. Beachten Sie, dass der 80386 32-Bit-Offsetregister kennt, der 8086 dagegen nicht. Virtuelle 8086-Tasks können daher durch das Address-Override-Präfix lineare 32-Bit-Adressen erzeugen. Übersteigt der Wert eines 80386-Offsetregisters im Virtual Mode den Wert 65535 oder ffffh, so löst die CPU eine Pseudo-Protection-Exception 0ch oder 0dh aus, ohne einen Fehlercode anzugeben. Die Kombination eines Segments ffffh und eines Offsets ffffh führt wie im gewöhnlichen Real Mode zu einer Adresse 10ffefh. Auch im Virtual Mode wird also die 1 MByte-Grenze um knapp 64 KByte durchbrochen.

Einstieg in den und Ausstieg aus dem Virtual-8086-Mode

Der Prozessor wird in den Virtual Mode versetzt, wenn das Flag VM (Virtual Mode) im EFlag-Register gesetzt wird. Das ist nur durch Codes mit Privilegierungsstufe 0, einen Task Switch mit Hilfe eines 80386-TSS oder eines IRET-Befehls, der die EFlags mit gesetztem VM-Bit vom Stack holt, möglich. Beachten Sie, dass der Prozessor dazu bereits im Protected Mode arbeiten muss. Ein direkter Einstieg vom Real in den Virtual-8086-Mode ist nicht möglich. Ein Task Switch lädt die EFlags automatisch aus dem TSS des neu gestarteten Tasks. Dadurch ist es nicht notwendig, dass das Betriebssystem von sich aus bei jedem Task Switch entscheidet, ob der neu gestartete Task im Protected oder Virtual-8086-Mode ausgeführt werden soll. Vielmehr nimmt das TSS dem Betriebssystem diese Entscheidung ab, es muss nur beim Erstellen des TSS für den Task einmal über den EFlag-Eintrag festlegen, ob der Task dann immer im Virtual-8086-Mode ausgeführt wird. Ein 80286-TSS kann durch die Beschränkung des Flag-Eintrags auf 16 Bit das höherwertige Wort im EFlag-Register, in dem sich das VM-Flag befindet, dagegen nicht verändern.

Umgekehrt verlässt der Prozessor den Virtual Mode, wenn das VM-Flag gelöscht wird. Gelöscht wird das VM-Flag durch ein 80386-TSS oder einen Interrupt beziehungsweise eine Exception, die ein Trap- oder Interrupt Gate aufruft. Die CPU kehrt dann in den gewöhnlichen Protected Mode zurück, um andere (Protected Mode) Tasks auszuführen. In Abbildung "Noch übersichtlich" ist dies genauer dargestellt.

Im Virtual Mode stehen alle 8086-Register, ihre Erweiterungen auf 32 Bit (durch das vorangestellte E) und zusätzlich die spezifisch mit dem 80386 eingeführten Register wie FS, GS, Debug-Register et cetera zur Verfügung. Außerdem können auch die mit dem 80186, 80286 und 80386 eingeführten Befehle wie BOUND, LSS et cetera benutzt werden. Den Virtual-8086-Mode könnte man also eher als Virtual-i386-Real Mode bezeichnen.

Tasks im Virtual-8086-Mode

Das 8086-Programm selbst (Real Mode), der Virtual-8086-Monitor (Protected Mode) und die Betriebssystemfunktionen für das 8086-Programm (Real oder Protected Mode) bilden zusammen einen Virtual-8086-Task, der durch ein 80386-TSS dargestellt wird. Dadurch kann der Virtual-8086-Task wie ein anderer, speziell für den Protected Mode konzipierter Task durch einen Task Switch mittels des TSS aufgerufen werden. Es findet demnach Multitasking mit einem bisher nicht multitasking-fähigen Programm statt, denn das 8086-Programm kann in die Multitasking-Umgebung eingebettet werden.

Der Virtual-8086-Monitor läuft im Protected Mode mit der Privilegierungsstufe 0 und weist Routinen auf, um das 8086-Programm zu laden und Interrupts und Exceptions zu behandeln. Demgegenüber läuft das "eigentliche" 8086-Programm mit einer Privilegierungsstufe CPL=3. Wie beim Real Mode sind im Virtual Mode die ersten 10fff0h Byte des linearen Adressraums vom Prozessor (von 4 GByte gleich 100 000 000h) durch das 8086-Programm belegt. An dieser Stelle möchte ist zu erwähnen, dass der Paging-Mechanismus auch im Virtual-8086-Mode die lineare auf eine völlig andere physikalische Adresse abbildet und dadurch viele lineare Adressräume 0000:0000h bis 1000:fff0h erzeugen kann. Adressen außerhalb dieses Bereiches kann das 8086-Programm nicht bilden, so dass die Adressen über 10ffefh für den Virtual-8086-Monitor, das 32-Bit-Betriebssystem und andere Software zur Verfügung stehen.

Für einen Virtual-8086-Task fehlen nun noch die Betriebssystemfunktionen des 8086-Betriebssystems (beispielsweise MS-DOS). Für deren Implementierung gibt es prinzipiell zwei Möglichkeiten:

Der Vorteil der ersten Möglichkeit besteht darin, dass das bisherige Real-Mode-Betriebssystem nahezu unverändert übernommen werden kann. Jeder Virtual-8086-Task besitzt seine eigene und exklusiv für ihn reservierte Kopie von MS-DOS oder einem anderen Real-Mode-Betriebssystem. Damit können in einem 32-Bit-Prozessor gleichzeitig mehrere verschiedene Betriebssysteme laufen: das alles überwachende Betriebssystem für die Protected-Mode-Programme sowie die verschiedenen 8086-Betriebssysteme für die 8086-Programme im Virtual-8086-Mode. Es gibt aber ein gravierendes Problem: Die Betriebssystemfunktionen von MS-DOS und anderen Systemen werden über Interrupts aufgerufen, Interrupt Handler aber sind höchst kritische Bereiche eines Betriebssystems, das im Protected Mode arbeitet.

Sollen mehrere Virtual-8086-Tasks parallel ablaufen, so ist deren Koordination einfacher, wenn man von der zweiten Möglichkeit Gebrauch macht. In diesem Fall wird das Real-Mode-Betriebssystem der 8086-Tasks meist durch Aufrufe des 32-Bit-Betriebssystems emuliert.

Im Protected Mode reagieren die I/O-Befehle auf den Wert des IOPL-Flags. Ein zu großer Wert von CPL gegenüber IOPL führt zu einer Exception. Im Virtual Mode sind diese I/O-Befehle demgegenüber aber nicht vom IOPL-Flag abhängig - der Schutz des I/O-Bereiches erfolgt allein über die I/O-Permission-Bit-Map. Stattdessen reagieren nun die Befehle PUSHF, POPF, INTn, IRET, CLI und STI auf den Wert von IOPL, da ja die Befehle PUSHF, POPF, CLI und STI Flags verändern können. Die Veränderung der Flags ist in einer 32-Bit-Umgebung alleinige Aufgabe des Virtual-8086-Monitors oder des Betriebssystems und nicht des antiquierten und untergeordneten MS-DOS-Programms.

Die Interrupts

Durch die Abhängigkeit der Befehle INTn und IRET von IOPL hat der Virtual-8086-Monitor die Möglichkeit, Betriebssystemaufrufe des 8086-Programmes via Interrupts abzufangen. Ist der Wert von IOPL kleiner als 3, dem CPL des 8086-Programms also, so fängt der Monitor den Interrupt ab. Ist das 8086-Betriebssystem Teil des 8086-Programms, so gibt der Monitor den Interrupt an dieses weiter, wobei deren Aufruf und Ergebnis gegebenenfalls an die 32-Bit-Umgebung angepasst werden. Ansonsten kann der Monitor die betreffende Funktion des 8086-Betriebssystems direkt emulieren. Beachten Sie aber, dass die Interrupts im Real und Protected Mode sehr verschieden aussehen.

Da das 8086-Programm für einen 8086-Prozessor (oder eine andere CPU im Real Mode) geschrieben worden ist, besitzt der Virtual-8086-Task eine Interrupt-Vektortabelle im Real-Mode-Format CS:IP. Sie beginnt bei der linearen Adresse 0h und ist 1 KByte groß. Der 80386 verwendet aber im Virtual-8086-Mode diese Tabelle nicht direkt, sondern ruft bei einem INT-Befehl des 8086-Programms erst den entsprechenden Betriebssystem-Handler über die IDT auf. Er verlässt also den Virtual-8086-Mode. Den Ablauf eines Interrupts im Virtual-8086-Mode sehen Sie in Abbildung "Komplex".

Wie normalerweise bei einem Interrupt auch, legt der Prozessor die EFlags auf dem Stack ab. So kann der aufgerufene Handler anhand der abgelegten Flags erkennen, ob vorher das VM-Flag gesetzt worden war, das heißt ob der Interrupt einen Virtual-8086-Task unterbrochen hat. War VM gesetzt, überträgt der Interrupt Handler die Steuerung an den Virtual-8086-Monitor. Dieser kann nun wiederum den Interrupt selbst behandeln oder die Steuerung nochmals weitergeben, nämlich an den Interrupt-Handler des 8086-Programms. Dazu untersucht er die Interrupt-Vektortabelle des unterbrochenen 8086-Tasks, um den Einsprungpunkt des Real Mode Interrupt Handlers zu ermitteln. Durch ein IRET (mit der Privilegierungsstufe PL=0 des Monitors) schaltet der Prozessor wieder in den Virtual-8086-Mode um und ruft diesen Handler auf. Nach Abarbeitung des Real-Mode-Interrupt-Handlers führt der abschließende IRET-Befehl des Real-Mode-Handler erneut zum Virtual-8086-Monitor.

Nachdem dieser die Stacks für den Rücksprung angeglichen hat, führt er einen weiteren IRET aus. Damit setzt der Prozessor das vom Interrupt unterbrochene Programm fort. Der Interrupt ist hier über den Umweg IDT-Monitor-Handler vom Real-Mode-Handler des 8086-Tasks bedient worden. Wie Sie unschwer erkennen können, gibt ein Interrupt Anlass zu einer recht umfangreichen und dadurch auch langwierigen Prozedur. Ab dem Pentium ist der Vorgang optimiert worden.

Viele MS-DOS-Programme setzen und löschen das Interrupt-Flag IE, um die Bedienung von Hardware-Interrupts in kritischen Codeabschnitten zu steuern. Einen solchen Eingriff kann das 32-Bit-Betriebssystem, das für die gesamte Maschine verantwortlich ist, natürlich nicht dulden. Im Virtual-8086-Mode sind daher auch die Befehle PUSHF, POPF, CLI und STI von IOPL abhängig, weil sie direkt (CLI, STI) oder indirekt (PUSHF, POPF) das IE-Flag verändern können.

Der Virtual-8086-Monitor fängt solche, die Reaktion des gesamten Systems beeinflussenden, Befehle ab und verarbeitet sie in einer Weise, die das 32-Bit-System nicht nachteilig beeinflussen. Der Eingriff des Monitors bezüglich der von IOPL abhängigen Befehle für das 8086-Programm aber ist völlig transparent: Das 8086-Programm hat den Eindruck, als ob diese Befehle in der gewohnten Weise ausgeführt würden.

Die I/O-Ports

Einen weiteren für Multitasking-Systeme kritischen Bereich bilden die I/O-Ports, da mit ihrer Hilfe auf die Register der Hardware-Komponenten zugegriffen werden kann. Auch da kann es das Betriebssystem nicht dulden, vom 8086-Programm umgangen zu werden. Viele Real-Mode-Programme greifen nun aber direkt auf I/O-Ports zu - während in Multitasking-Systemen die meisten Programme nur über den Umweg des Betriebssystems, das die Zugriffe koordiniert, auf I/O-Ports zugreifen dürfen. Ein fehlerhafter Task soll ja schließlich nicht auch noch andere Tasks in Mitleidenschaft ziehen. Im Virtual Mode wird dieses Problem gelöst, indem die kritischen Ports durch die I/O Permission Bit Map geschützt werden, nicht aber durch das IOPL-Flag. Damit kann der Virtual-8086-Monitor dem 8086-Programm einerseits erlauben, direkt auf unkritische I/O-Ports zuzugreifen. Wenn zum Beispiel ein 8086-Programm gezielt eine Steckkarte für die Steuerung eines Roboters programmiert, deren Register von keinem anderen Programm benutzt werden, tritt für diese Ports niemals ein Konflikt auf - der Umweg über das Betriebssystem dagegen würde nur zu Verzögerungen führen, aber keinerlei Vorteil bringen. Andererseits werden dadurch kritische Ports wie beispielsweise die Register des Festplattencontrollers geschützt. Der Virtual-8086-Monitor fängt solche Zugriffe ab und behandelt sie in einer Weise, dass sie die anderen Tasks des Systems nicht stören.

Serie: x86-Programmierung und -Betriebsarten

Teil 1

Code-/Datensegment, Befehlszähler und Stack

Teil 2

Adressierungsarten und Befehlsdekodierung sowie Real Mode

Teil 3

Interrupts und Exceptions

Teil 4

Der Protected Mode

Teil 5

Paging

Teil 6

Der Virtual-8086-Modus

Diese Artikelserie basiert auf dem Kapitel 6 des "PC Hardwarebuch" von Addison- Wesley. Sie können in unserem Buch-Shop das über 1200 Seiten starke Kompendium bestellen oder als eBook downloaden.

tecCHANNEL Buch-Shop

Weitere Literatur zum Thema Hardware

Titelauswahl

Titel von Pearson Education

Bücher

PDF-Titel (50% billiger als Buch)

Downloads