Aus dem Zusammenwirken von Busschnittstelle, Prefetch-Queue, Ausführungseinheit et cetera des Prozessors ist unschwer zu erkennen, dass die CPU unaufhörlich Befehle ausführt. Hat sie einen Befehl abgearbeitet, so wird der nächste geladen und ausgeführt. Auch wenn Ihr PC scheinbar darauf wartet, dass Sie einen Befehl oder Text eingeben, bedeutet das nicht, dass der Prozessor auch wirklich angehalten wird, um erst mit Ihrer Eingabe die Arbeit wieder aufzunehmen. Vielmehr läuft im Hintergrund eine Routine ab, die ständig die Tastatur überprüft, um zu ermitteln, ob Sie bereits ein Zeichen eingetippt haben. Es wird also eine Programmschleife ausgeführt.
In Abhängigkeit von der Quelle einer Unterbrechung (der deutsche Ausdruck für Interrupt) unterscheidet man drei Kategorien von Interrupts:
Software-Interrupts
Hardware-Interrupts
Exceptions (Ausnahmen)
| |
Teil 1 | |
---|---|
Teil 2 | |
Teil 3 | Interrupts und Exceptions |
Teil 4 | Der Protected Mode |
Teil 5 | Paging und die MMU |
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.
Software-Interrupts
Ein Software-Interrupt wird gezielt durch einen INT-Befehl ausgelöst. Zum Beispiel ruft der Befehl INT 10h den Interrupt mit der Hex-Nummer 10h auf. Das Bild "Prozedur" zeigt den Ablauf, der bei einem Interrupt im Real Mode ausgeführt wird. Ein Interrupt-Vektor ist eine Adresse im Format Segment:Offset, die auf den Einsprungpunkt des zugehörigen Handlers zeigt. Der 80386 lädt EIP und CS mit den Werten in der Tabelle.
Im Real-Mode-Adressraum sind die ersten 1024 Byte (1 KByte) für die Interrupt-Vektortabelle reserviert. Diese Tabelle weist für jeden der 256 möglichen Interrupts einen so genannten Interrupt-Vektor auf. Von allen Speicherverwaltungsregistern besitzt das Interrupt-Deskriptor-Table-Register IDTR bereits im Real Mode eine Bedeutung. Es speichert nämlich die Basisadresse und das Limit der Real-Mode-Deskriptortabelle.
Nach einem Prozessor-Reset wird das IDTR standardmäßig mit den Werten 00000000h für die Basis und 03ffh für das Limit geladen. Das entspricht exakt einer 1-KByte-Tabelle bei Segment 0000h, Offset 0000h. Durch die Befehle LIDT (Load IDTR) und SIDT (Store IDTR) können die beiden Werte aber verändert und die Tabelle dadurch mit anderer Größe an eine beliebige Stelle des Real-Mode-Adressraums verschoben werden. Achten Sie aber darauf, dass die Tabelle auch alle Vektoren für die möglicherweise auftretenden Interrupts aufnehmen kann. Sonst ist eine Exception 8 die Folge.
Interrupt-Vektoren
Jeder Interrupt-Vektor ist 4 Byte lang und gibt im Intel-Format die Adresse Segment:Offset des Interrupt-Handlers an, der den Interrupt bedient. Da ein Interrupt meist eine bestimmte Ursache hat, wie die Anforderung einer Betriebssystemfunktion, der Empfang eines Zeichens über die serielle Schnittstelle et cetera, behandelt der Interrupt-Handler diese Ursachen in geeigneter Weise. Er führt also beispielsweise die Betriebssystemfunktion aus oder nimmt das empfangene Zeichen entgegen. Durch Ersetzen des Handlers kann einem Interrupt auf einfache Weise eine andere Funktion zugeordnet werden.
Die Zuordnung von Interrupt und Interrupt-Vektor erfolgt auf einer Eins-zu-eins-Basis, das heißt, dem Interrupt 0 wird der Interrupt-Vektor 0 (an der Adresse 0000:0000), dem Interrupt 1 der Interrupt-Vektor 1 (an der Adresse 0000:0004) und so weiter zugeordnet. Damit muss nur die Nummer des Interrupt mit 4 multipliziert werden, und man erhält den Offset des Interrupt-Vektors im Segment 0000h. Der Prozessor führt genau diese Multiplikation aus, um aus der Interrupt-Nummer dessen Adresse zu ermitteln. Neben dem Bereich f000:fff0 bis f000:ffff für den Prozessor-RESET existiert damit ein zweiter für den Prozessor reservierter Adressbereich. Diese Adressbereiche stehen für Anwendungsprogramme nicht zur Verfügung. Ein Überschreiben der Interrupt-Vektortabelle mit ungültigen Werten hat katastrophale Folgen: Beim nächsten Interrupt stürzt der Rechner ab.
Interrupt-Prozedur
Beim Aufruf eines Interrupt läuft nun folgende Prozedur (siehe Bild "Prozedur" im Abschnitt "Software-Interrupts") ab, die ab dem 80386 automatisch und ohne weiteres Eingreifen eines Programms ausgeführt wird:
Die CPU schiebt die EFlags, CS und EIP - in dieser Reihenfolge - auf den Stack (im 16-Bit-Modus natürlich nur Flags, CS und IP).
Das Interrupt- und Trap-Flag werden gelöscht.
Die CPU adressiert den Interrupt-Vektor in der Interrupt-Vektortabelle entsprechend der Nummer des Interrupt und lädt EIP (oder IP im 16-Bit-Modus) sowie CS aus der Tabelle.
CS:EIP des Interrupt-Vektors gibt den Einsprungpunkt des Interrupt-Handlers an. Damit setzt der Prozessor seine Arbeit mit dem Interrupt-Handler fort. Die Rückkehr zum aufrufenden Programm erfolgt über ein IRET. Beispiel:
INT 10h
Der Prozessor schiebt die aktuellen Flags, CS und EIP auf den Stack, löscht das Interrupt- und Trap-Flag und liest den Interrupt-Vektor an der Adresse 0000:0040. Die zwei Bytes bei 0000:0040 werden in EIP, die beiden Bytes bei 0000:0042 in CS geladen (beachten Sie das INTEL-Format low-high).
Die CPU lädt den Offset-Wert des Handlers im 32-Bit-Modus zwar in EIP, aber der Offset in der Interrupt-Vektortabelle umfasst aus Kompatibilitätsgründen mit den 16-Bit-Vorgängern 8086 und 80286 des 80386 nur 16 Bit. Die zwei höher wertigen Bytes in EIP werden dann einfach mit dem Wert 0000h aufgefüllt.
Von Interesse ist auch die Kodierung des INT-Befehls: 11001100 beziehungsweise 11001101 stellt den Opcode dar, und vvvvvvvv gibt die Nummer des Interrupt an: Der Befehl INT 3 besteht also aus nur einem Byte. Im Abschnitt Exceptions erfahren Sie Näheres zu diesem Interrupt. Für alle anderen INT-Befehle ist nur eine unmittelbare Adressierung möglich, das heißt, die Nummer des Interrupt-Vektors ist Teil des Befehlsstroms. Damit kann die Nummer des Interrupt nicht in einem Register oder Speicheroperanden bereitgehalten werden.
Software-Interrupts treten synchron zur Programmausführung auf, das heißt, jedes Mal, wenn das Programm den Punkt mit dem INT-Befehl erreicht, wird ein Interrupt ausgelöst. Das unterscheidet sie wesentlich von den Hardware-Interrupts und Exceptions.
Hardware-Interrupts
Wie schon der Name sagt, werden diese Unterbrechungen durch einen Hardware-Baustein oder ein Peripheriegerät wie beispielsweise eine Schnittstellenkarte ausgelöst. Man unterscheidet zwei grundsätzlich verschiedene Arten von Hardware-Interrupts: den nicht maskierbaren Interrupt NMI sowie den (maskierbaren) Interrupt IRQ. Für die Bedienung eines solchen IRQs spielt der Interrupt-Controller eine große Rolle, denn er verwaltet mehrere Interrupt-Anforderungen und gibt sie geordnet nach ihrer Priorität gezielt an den Prozessor weiter.
Löst der Computer einen NMI aus, so wird dem NMI-Anschluss des Prozessors ein aktives Signal zugeführt. Die CPU arbeitet den gerade ausgeführten Befehl ab und führt unmittelbar anschließend in gleicher Weise wie oben einen Interrupt 2 aus. Beim PC wird ein NMI ausgelöst, wenn beim Lesen von Daten aus dem Speicher ein Paritätsfehler oder ein anderes ernstes Hardware-Problem, wie zum Beispiel eine fehlerhafte Busarbitrierung, auftritt. Der Computer meldet sich dann bei einem Paritätsfehler mit der folgenden (oder einer ähnlichen) Nachricht:
Paritätsfehler bei xxxx:xxxx
xxxx:xxxx gibt das Byte mit dem Paritätsfehler an. Die Besonderheit des NMI ist, dass er (wie auch hier bereits der Name ausdrückt) nicht unterdrückt, das heißt maskiert, werden kann. Ein NMI drängelt sich immer nach vorne. Da er normalerweise nur bei einer wirklich schwerwiegenden Fehlfunktion der Hardware ausgelöst wird, ist dies aber verständlich und auch richtig.
IRQs
Demgegenüber können Interrupt-Anforderungen via IRQ maskiert werden, indem man mit CLI das Interrupt-Flag IE löscht. Alle Interrupt-Anforderungen über den Anschluss INTR (Pin B7, beim 80386) werden ignoriert. Erst durch den umgekehrten Befehl STI werden solche Interrupts wieder zugelassen. Beachten Sie dabei, dass der Software-Befehl INT xx implizit ein CLI ausführt. Sie müssen also nach einem INT-Befehl explizit mit einem STI Interrupt-Anforderungen wieder zulassen, sonst wird der Computer taub. Interrupt-Anforderungen werden üblicherweise durch ein Peripheriegerät ausgelöst, beispielsweise, wenn die serielle Schnittstelle dem Prozessor mitteilen möchte, dass sie gerade ein Zeichen empfangen hat.
Hardware-Interrupt-Anforderungen werden durch den Interrupt-Controller (im Chipset) verwaltet. Empfängt dieser ein Signal, das anzeigt, dass ein Hardware-Interrupt ausgelöst werden soll, so führt er dem INTR-Eingang der CPU ein Anforderungssignal (Interrupt-Request) zu. Kann der Prozessor den Interrupt bedienen (ist IE gesetzt), gibt er ein Bestätigungssignal INTA (Interrupt Acknowledge) aus, indem er die Steuersignale M/IO, D/C und W/R jeweils auf einen niedrigen Pegel setzt. Die CPU erhält dann vom Interrupt-Controller die Nummer des auszuführenden Interrupt. Der Prozessor fährt nun in gleicher Weise wie oben beschrieben fort und ruft den entsprechenden Interrupt-Handler auf.
Hardware-Interrupts (NMI und IRQ) sind im Gegensatz zu Software-Interrupts völlig asynchron zur Programmausführung. Beispielsweise benötigt die Festplatte in Abhängigkeit von der Ausgangsstellung der Schreib-/Leseköpfe eine unterschiedliche Zeitspanne, bis die Daten zum Prozessor übertragen werden können. Dies macht die Erfassung von Programmfehlern sehr schwierig, wenn sie nur im Zusammenwirken mit Hardware-Interrupts auftreten.
Exceptions
Zwei Quellen für Interrupts haben wir bereits kennen gelernt, eine dritte bildet der Prozessor selbst. Interrupts, die vom Prozessor erzeugt werden, bezeichnet man als Exceptions (Ausnahmen). Die Auswirkungen einer Exception entsprechen dabei einem Software-Interrupt, das heißt, es wird ein Interrupt aufgerufen, dessen Nummer in diesem Fall vom Prozessor selbst angegeben wird. Ursache für eine Exception ist im Allgemeinen eine prozessorinterne Fehlerbedingung, die den Eingriff von System-Software erfordert und vom Prozessor nicht mehr allein behandelt werden kann.
Exceptions werden nach drei Klassen unterschieden: Faults, Traps und Aborts. Im Folgenden möchten wir kurz die Kennzeichen der drei Klassen beschreiben.
Fault: Ein Fault löst eine Exception aus, bevor der Befehl vollständig ausgeführt wird. Der gesicherte EIP-Wert zeigt damit auf den Befehl, der die Exception ausgelöst hat. Durch Laden des gesicherten EIP-Werts (zum Beispiel über IRET) kann der Prozessor den Befehl nochmals ausführen, hoffentlich ohne erneut eine Exception auszulösen. Ein Beispiel für einen Fault wäre die Exception "Segment nicht vorhanden". Der Prozessor hat dann die Möglichkeit, das Segment nachzuladen und einen erneuten Zugriffsversuch zu wagen.
Trap: Ein Trap löst dagegen eine Exception aus, nachdem der Befehl ausgeführt worden ist. Der gesicherte EIP-Wert zeigt also auf den Befehl unmittelbar nach dem Befehl, der die Exception ausgelöst hat. Der Befehl wird also nicht nochmals ausgeführt. Traps sind günstig, wenn der Befehl zwar korrekt ausgeführt worden ist, aber das Programm trotzdem unterbrochen werden soll. Das gilt zum Beispiel für die Haltepunkte eines Debuggers; hier sollen die Befehle ja ausgeführt werden, und nur der Debugger prüft dann die Registerinhalte et cetera. Ein nochmaliges Ausführen des entsprechenden Befehls würde zu einem fehlerhaften Befehlsfluss führen.
Abort: Ein Abort liefert im Gegensatz zu Faults und Traps nicht immer die Adresse des Fehlers. Dadurch kann nach einem Abort die Programmausführung mitunter nicht wieder aufgenommen werden. Aborts werden nur dazu benutzt, äußerst schwerwiegende Fehlfunktionen anzuzeigen, wie zum Beispiel Hardware-Ausfälle oder ungültige Systemtabellen.
Exceptions im Real Mode
Ein großer Teil der Exceptions ist für den Betrieb im Protected Mode vorgesehen. Im Real Mode sind nur die folgenden Exceptions von Bedeutung:
Division durch 0 (Exception 0): Ist bei einem Befehl DIV oder IDIV der Divisor gleich Null, dann ist das Ergebnis der Operation nicht einmal mathematisch definiert. Ist eine Division nicht nach einer bestimmten Zahl von Taktzyklen beendet, ermittelt die Steuereinheit eine Division durch 0 und löst eine Exception 0 aus.
Einzelschritt (Exception 1): Ist das Trap-Flag gesetzt worden, so löst der Prozessor nach jedem einzelnen ausgeführten Befehl eine Exception 1 aus. Da das Trap-Flag beim Aufruf eines Interrupt automatisch gelöscht wird, kann der Prozessor die Interrupt-Routine ohne Unterbrechung ausführen. Häufig setzen Debugger das Trap-Flag und fangen den Interrupt ab, um ein Programm schrittweise ausführen zu können.
Breakpoint (Exception 3): Eine Breakpoint-Exception kann prinzipiell auf zweierlei Weise zu Stande kommen. Die CPUs besitzen interne Debug-Register, mit deren Hilfe sie unter bestimmten Umständen einen Interrupt 3 erzeugen. Außerdem kann ein Debugger an der Stelle eines Befehls einen Breakpoint setzen, indem er den Befehl (oder dessen erstes Byte) mit dem Opcode 11001100 für den Befehl INT 3 überschreibt. Erreicht die Ausführung des Programms diesen Punkt, so wird eine Exception 3 ausgelöst, der Programmablauf also unterbrochen. Um das Programm fortzusetzen, überschreibt der Debugger den Opcode 11001100 mit dem ursprünglich an dieser Stelle vorhandenen Byte und führt ein IRET aus. Natürlich kann der Prozessor auch durch einen expliziten Befehl INT 3 einen Software-Interrupt 3 auslösen. Das geht auch bei allen anderen Exceptions, nur liegt eigentlich kein Grund für den folgenden Interrupt vor, weil die Quelle des Interrupt nicht in einer Fehlerbedingung im Prozessor liegt, sondern in einem expliziten Software-Interrupt.
Überlauferfassung mit INTO (Exception 4): Ist das Overflow-Flag gesetzt und wird der Befehl INTO ausgeführt, so erzeugt der Prozessor eine Exception 4.
BOUND (Exception 5): Liegt der mit dem Befehl BOUND geprüfte Index in einem Feld außerhalb der Grenzen des Feldes, so wird eine Exception 5 erzeugt.
Ungültiger Opcode (Exception 6): Stößt die Befehlseinheit auf einen Opcode, dem kein Befehl zugeordnet werden kann, so löst der Prozessor eine Exception 6 aus. Ursache für ungültige Opcodes sind meistens fehlerhafte Assembler oder Compiler oder ein Programmfehler, der zu einem Sprung an einer Stelle führt, bei der eigentlich kein Opcode, sondern zum Beispiel ein Datenwort steht, die Befehlseinheit das Datenwort entsprechend dem Programmfluss aber als Opcode interpretiert.
Kein Coprozessor vorhanden (Exception 7): Erfasst die Befehlseinheit einen Opcode, der einen Befehl für den Coprozessor angibt (also einen ESC-Befehl) und ist gar kein Coprozessor vorhanden, so löst die CPU eine Exception 7 aus.
IDT-Limit zu klein (Exception 8): Ist das Limit der IDT zu klein, um den Vektor des ausgelösten Interrupt aufzunehmen, dann führt das zu einer Exception 8. Das ist meist der Fall, wenn ein Programm die IDT angesprochen und in unkorrekter Weise verändert hat.
Stack-Exception (Exception 12): Der Stapelzeiger ESP lieferte einen größeren Wert als ffffh für den Stack-Zugriff. Das kann vorkommen, weil ESP ein 32-Bit-Register darstellt und sein Wert nicht auf unter 1M beschränkt ist. Eine Exception 12 ist die Folge, um die Erzeugung von linearen Adressen über 10ffefh im Real Mode zu unterbinden.
Allgemeiner Protection-Fehler (Exception 13): Ein 32-Bit-Offset-Register lieferte eine größere effektive Adresse als ffffh für einen Speicherzugriff. Wie für den Stapelzeiger ESP wird dadurch die Erzeugung von linearen Adressen über 10ffefh im Real Mode unterbunden, und der Prozessor löst eine Exception 13 aus.
Coprozessor-Fehler (Exception 16): Im Coprozessor(teil) ist ein Fehler aufgetreten, und der Prozessor hat das dadurch aktivierte Signal ERROR erfasst. Die Folge ist ein Interrupt 16.
Ausblick
Der nächste Teil der Artikelserie widmet sich einer besonderen Spezialität der x86-Prozessoren - dem Protected Mode. Wir werden diese Betriebsart anhand von zahlreichen Bildern ausführlich erläutern.
| |
Teil 1 | |
---|---|
Teil 2 | |
Teil 3 | Interrupts und Exceptions |
Teil 4 | Der Protected Mode |
Teil 5 | Paging und die MMU |
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.
Weitere Literatur zum Thema Hardware | Titelauswahl |
---|---|
| |
Titel von Pearson Education | |
PDF-Titel (50% billiger als Buch) |