home *** CD-ROM | disk | FTP | other *** search
-
-
- Interrupts auf dem PC
-
- oder die Kunst, residente Programme wieder zu entfernen
-
- von Karsten Gieselmann
-
- Das Zauberwort bei PC-Software heißt TSR - Terminate but Stay
- Resident. Doch so nützlich TSR-Programme auch sind, oft ist ein
- Entfernen dieser "RAM-Fresser" nötig, sei es aus
- Speicherplatzmangel oder aus Gründen der Unverträglichkeit. Für
- selbstgeschriebene TSR- Anwendungen ist der "Griff zum
- Wegschmeißen" noch relativ einfach anzubringen, aber was tun
- bei kommerzieller oder Public- Domain-Software? Der folgende
- Beitrag führt Sie in anhand der Lösung dieses Problems
- praxisnah in die Tiefen und Höhen des Themas "Interrupts auf
- dem PC" ein.
-
-
- Wie funktioniert überhaupt ein TSR- Programm, was geschieht
- beim Laden und beim resident machen? Zunächst ist eine solche
- TSR-Anwendung für das DOS ein ganz normales Programm, das wie
- jedes andere Anwenderprogramm in den Speicher geladen und
- ausge- führt wird. DOS teilt das ihm zur Verfügung stehende RAM
- nach einem festen Schema auf.
-
- Die TSR-Philosophie: Oft gebrauchte Programme verbleiben
- dauernd im Arbeitspeicher
-
- Wenn bisher überhaupt noch keine Programme gestartet worden
- sind, so wird das erste aufgerufene Programm direkt hinter das
- DOS geladen und dann abgearbeitet. Handelt es sich bei diesem
- Programm nicht um eine Resident-Anwendung, also wirklich um
- ein "normales" Programm, so endet es mit einem Befehl, der
- die Kontrolle wieder an den Kommandoprozessor COMMAND.COM
- übergibt und den belegten Speicherplatz freimacht. Auf diese
- Weise wird das nächste Programm an die gleiche Stelle wie der
- Vorgänger geladen.
-
- Gehört das Programm hingegen zum Typ "TSR", so endet es mit
- einem Befehl, der die Kontrolle zwar ebenfalls an den
- Kommandoprozessor übergibt, den vom Programm belegten
- Speicherplatz aber nicht wieder freimacht: Das Programm
- verbleibt an der Stelle im Speicher, an die es zur Ausführung
- geladen wurde. Außerdem merkt sich das DOS dies und erhöht die
- Anfangsadresse für das nächste aufgerufene Programm auf den
- Wert, welcher der letzten vom TSR-Programm belegten Speicher-
- stelle folgt. Damit ist der für Benutzerprogramme zur Verfügung
- stehende Speicherplatz geringer geworden!
-
- Machen wir ein Beispiel: DOS hat auf diese Weise die residenten
- Programme KEYBGR, CLOCK, DOSEDIT und HYPERKEY geladen. Damit
- sieht die RAM-Belegung wie in Abbildung 2 dargestellt aus.
-
- Gehen wir nun der Frage nach, wie die geladenen TSR's wieder
- zum Einsatz kommen, sind wir mitten im Thema "Interrupts". Denn
- in der Regel machen sich diese Programme dadurch bemerkbar, daß
- sie sich an den für das Betriebssystem lebenswichtigen
- Interruptvektoren zu schaffen machen.
-
- Interupts sind für einen Rechner immens wichtig: Ohne sie geht
- nichts
-
- Mit Interruptvektor bezeichnet man eine Unterpro- grammadresse,
- die an einer festen Speicherstelle im RAM "gemerkt" wird. Das
- DOS kennt eine ganze Reihe von solchen Interruptvektoren,
- insgesamt 256 Stück, und merkt sich deren Adressen, jeweils 4
- Bytes, Segment und Offset, in der sogenannten Interrupt-
- tabelle im Bereich von 0:0 bis 0:FFh.
-
- Die Vektoren zeigen auf wichtige Unterprogramme, auch
- Interrupt- Service-Routine (ISR) genannt, ohne die ein Rechner
- überhaupt nicht funktionieren könnte. Von einem TSR-Programm
- wird eben diese Interrupt-Tabelle manipuliert:
-
- Zur Erklärung: durch das Auslösen von Interrupts kön- nen
- Programme (Software- Interrupts) und Peripherie- geräte
- (Hardware-Interrupts) erzwingen, daß die CPU den normalen
- Programmablauf unterbricht und zunächst eine spezielle Routine
- abarbeitet, die die vom Interruptauslöser angeforderten
- Maßnahmen trifft.
-
- Ein Beispiel: Drückt ein Anwender während eines lau- fenden
- Programms irgendeine Taste, so meldet die Tastatur der CPU
- dieses Ereignis durch Auslösen des Interrupt 9h. Für einen
- kurzen Augenblick, ein paar Millisekunden, wird die laufende
- Programmausführung unterbrochen und stattdessen "mal eben
- zwischendurch" dasjenige Unterprogramm abgearbeitet, auf
- welches der besagte Interruptvektor 9h zeigt: Die an der
- Tastatur bereit liegende Tastennummer abholen, entsprechend des
- aktuellen Umschaltstatus umcodieren und den resultierenden
- Tastencode im DOS- Tastaturpuffer placieren. Anschließend geht
- es dort mit der Ausfüh- rung weiter, wo zur
- Interruptbearbeitung abgebrochen wurde.
-
- Eine wichtige Anwendung von TSR's ist die Verbesse- rung von
- Systemdiensten: Z.B. ein Spooler für die Druckeransteuerung,
- ein Kommandozeilen-Editor für die Eingabe von DOS-Kommandos
- oder ein Cache-Speicher für den Zugriff auf
- Festplatte/Diskette. Diese Programme setzen in ihrem
- Initialisierungsteil, dem Programmteil, der direkt nach dem
- Laden und vor dem resident machen ausgeführt wird, einfach den
- für sie wichtigen Interruptvektor auf eine neue, eigene
- Routine, die den verbesserten Service bereitstellt.
-
- Viele der von TSR-Programmen installierten ISR's arbeiten dabei
- nicht völlig selbständig, sondern rufen Ihrerseits die vor dem
- Laden des TSR's gültige ISR wieder auf, bzw. setzen nach
- Abarbeitung der eigenen ISR die Programmausführung bei der
- alten ISR fort. Werden mehrere residente Programme geladen, die
- alle auf den gleichen Interruptvektor zugreifen, entsteht auf
- diese Weise eine Verkettung von Inter- ruptroutinen.
-
- Der Zugriff auf einen Interruptvektor, im Fachjargon
- "verbiegen" oder "anzapfen", ist das Husarenstück eines TSR-
- Programms
-
- Eine andere Art von TSR-Programmen sind die sogenann- ten Pop-
- Up-Routinen: Auf Knopfdruck erscheint ein Fenster, das Programm
- stellt seine Dienste bereit, um ebenfalls auf Knopfdruck wieder
- zu verschwinden und so zu tun, als ob überhaupt nichts passiert
- wäre.
-
- Diese TSR's manipulieren ebenfalls mindestens einen
- Interruptvektor: den für die Tastaturabfrage. Sobald irgendeine
- Taste gedrückt wird, prüft die für die Tastatur zuständige ISR
- des Pop-Up's, ob diese Taste vielleicht die Aktivierungstaste
- (neudeutsch: Hotkey) für das Pop-Up ist. Zur Ermittlung des
- Tastencodes wird dabei ebenfalls auf die "normale" Tastaturrou-
- tine zurückgegriffen, so daß'sich beim Laden mehrerer solcher
- Programme auch hier eine Interrupt-Kette bildet.
-
- Lenkt man an dieser Stelle die Gedanken in Richtung "Entfernen
- von residenten Programmen", so wird schnell klar, daß ein
- beliebiges Löschen von TSR's aus dem Arbeitsspeicher eine
- unsichere und gefährliche Sache ist: Unter Umständen wird mit
- einem TSR- Programm ein Glied aus einer Interruptkette
- entfernt.
-
- Wird solch eine unterbrochene Interruptkette durch- laufen, so
- zeigt irgendeine eine Sprungadresse in einen (theoretisch)
- nicht mehr belegten Bereich. Zumeist aber steht dort
- mittlerweise schon etwas ganz anderes als die erwartete ISR,
- denn das DOS vergibt freien Speicherplatz wieder an andere
- Prozesse. Die Programmausführung wird dann an einer Stelle
- fortge- setzt, an der sich keine ISR mehr befindet: Ein
- sicherer Absturz des Rechners ist die Folge.
-
- Wenn überhaupt TSR's entfernt werden können, dann höchstens von
- hinten nach vorne, also in der umge- kehrten Reihenfolge ihres
- Ladens: Nur so ist gewährleistet, daß Interruptketten intakt
- bleiben und alle Abläufe im Rechner weiterhin sicher vonstatten
- gehen.
-
- Der erste Schritt zu einer "Verwaltung" von speicher-
- residenten Programmen ist ein Belegungsplan: An welcher
- Stelle im RAM befindet sich welches Programm und wieviel
- Speicherplatz belegt es? Um diese Frage beantworten zu können,
- müssen wir uns im Folgenden etwas detaillierter mit der DOS-
- Speicherverwaltung auseinandersetzen.
-
- Das DOS organisiert seinen Hauptspeicher ganz ähn- lich, wie
- Turbo Pascal den Heap: in Form einer dynamisch verketteten
- Liste. Gemäß den Anforderungen werden über die DOS- Funktion
- 48h - ALLOCATE MEMORY von dem insgesamt zur Verfügung stehenden
- RAM mehr oder weniger große Stücke abgetrennt und als "belegt"
- gekennzeichnet. Bei der Freigabe solcher Bereiche durch die
- DOS-Funktion 49h - FREE ALLOCATED MEMORY werden diese wieder in
- die Freispeicherliste eingereiht.
-
- Die zu dieser Organisation in Turbo Pascal verwende- ten Zeiger
- heißen bei DOS "Memory Control Blocks" (MCB). Im Gegensatz zu
- einem gewöhnlichen Zeiger - im Grunde genommen nicht mehr als
- eine Adresse - enthält ein MCB mehrere Informationen und jedem
- vom DOS angelegten Speicherblock wird ein MCB vorangestellt.
- Die- ser besteht aus insgesamt fünf Bytes, die sich wie folgt
- aufgliedern:
-
-
- Byte Information
-
- 0 Kennung ("M" oder "Z")
- 1,2 Segmentadresse des Programms
- 3,4 Blockgröße (in Paragraphen)
-
- Das erste Byte enthält lediglich die Information, ob es sich
- bei diesem MCB schon um den letzten in der Kette handelt:
- trifft dies zu, so hat der MCB die Kennung "Z", anderenfalls
- die Kennung "M".
-
- Die Bytes 1 und 2 ergeben das zum Speicherblock gehörige
- Programmsegment. Beim Laden eines Programms werden vom DOS
- zwei verschiedene Speicherblöcke ange- legt. Der erste
- beinhaltet das eigentliche Programm (Code, Daten- und
- Stacksegment). Außerdem das jedem Programm vorangestellte
- "Program Segment Prefix" (PSP), ein 256 Bytes großer Abschnitt,
- der unter an- derem Informationen über die Adressen einiger
- wichtiger Interruptroutinen, die DOS-Parameterzeile und die
- Segmentadresse des zum Programm gehörigen Environments
- enthält.
-
- Die Kennzeichnung mit den Buchstaben "M" und "Z" hat seinen
- Grund: Es sind die Initialen des DOS-Autors, Mark Zbikovski.
-
- Der zweite Speicherblock wird von eben diesem Environment
- belegt, hier finden sich die Informationen, die mit dem SET-
- Befehl auf DOS-Ebene manipuliert werden können (PATH,
- COMSPEC, PROMPT, etc.). Ab der DOS- Version 3.0 wird zusätzlich
- im Environment-Block noch der Name des zugehörigen Programms
- vermerkt, er liegt hinter den Umgebungsvariablen und ist von
- diesen durch die Bytefolge 00,00,01,00 getrennt.
-
- Ist der Wert des Programm-Segments in einem MCB gleich Null, so
- bedeutet dies nichts weiter als das der folgende Speicherblock
- unbenutzt ist. Die Null wird dann vom DOS eingesetzt, wenn mit
- einer der dafür zuständigen DOS-Funktionen (48h, 4Ah) ein Spei-
- cherbereich wieder freigegeben wird und nicht an einen schon
- existierenden, freien Block angegliedert werden kann.
-
- Byte 3 und 4 geben schließlich die Größe des zum MCB gehörenden
- Speicherblocks in Paragraphen an. Ein Paragraph entspricht 16
- Bytes, eine Zahl, die man als das Zeigerelement eines MCB's
- interpretieren kann: Addiert man zur Segmentadresse eines MCB's
- die Blockgröße plus eins, da trotz seiner Größe von nur fünf
- Bytes ein MCB immer genau einen ganzen Paragraphen belegt, so
- ergibt sich die Segmentadresse des nächsten MCB's!
-
- Abbildung 3 zeigt in schematischer Darstellung, wie die
- Speicherverwaltung im DOS mit Hilfe der MCB's realisiert ist.
- Um eine Routine zu schreiben, welche sich mit Hilfe dieser
- MCB's durch das RAM hangelt und eine Liste aller vorhandenen
- Programme erstellt, benötigt man jetzt nur noch einen Einstieg:
- Die Adresse im Speicher, an welcher sich der erste MCB
- (sozusagen der Listenkopf) befindet.
-
- Diese Adresse, oder besser gesagt einen Zeiger darauf, liefert
- die von Microsoft nicht dokumentierte Funktion 52h des
- Interrupts 21h. Nach Aufruf dieser Funktion enthält das
- Registerpaar ES:BX die Adresse einer Tabelle, in der die
- verschiedensten Informationen vermerkt sind. Genau vor dieser
- Tabelle befindet sich die Segmentadresse des ersten im Speicher
- befindlichen MCB. Zu bemerken ist, daß die Offsetadresse
- eines MCB immer Null ist.
-
- Mit dem erarbeiteten Know-How läßt sich nun relativ problemlos
- eine Routine schreiben, welche Auskunft über die im Speicher
- befindlichen Programme gibt. Ausgegeben werden soll auf jeden
- Fall der Programmname, das Ladesegment, also die Stelle im
- RAM, wo sich das Programm befindet, und die Größe des vom
- Programm belegten Speicherplatzes. Da es Programme gibt, die
- nach dem Laden den Environment-Speicherblock wieder
- freigeben, z.B. die Treiber und residenten Dienstprogramme
- unter MS- DOS 3.2 wie KEYBGR oder PRINT, soll auch die Anzahl
- der zu einem PSP gehörigen Blöcke ausgegeben werden.
-
- Die Landkarte der RAM-Speicherbelegung misst in Paragraphen.
- Allerdings keine juristischen, denn in der Informatik ist der
- Paragraph 16 Bytes lang.
-
- Diese Leistungen werden durch die Turbo-Pascal-Unit MAKEMAP.INC
- zur Verfügung gestellt: Der Belegungsplan wird in Form einer
- doppelt verketteten dynamischen Liste angelegt. Die Funktion
- "MakeMemoryMap" liefert nach Rückkehr ins aufrufende Programm
- einen Zeiger auf den ersten Eintrag des Belegungsplans. Das ei-
- gentliche Programm MAP hat dannach außer der Ausgabe der Liste
- (die Abbildungen 4 und 5 zeigen typische Outputs von MAP)
- eigentlich nicht mehr viel zu tun.
-
- Es gibt jedoch noch einen Punkt, den es gleich mit erledigen
- kann: Gerade bei residenten Programmen ist es oft sehr nützlich
- zu wissen, welche Interrupt- Vektoren von einer Routine
- "umgebogen" werden. Dies läßt sich relativ einfach angeben: Für
- alle Einträge in der Interrupt-Tabelle wird überprüft, ob sie
- in das jeweilige Programm hineinzeigen. Ist dies der Fall, so
- kann man davon ausgehen, daß der zugehörige Interruptvektor vom
- betreffenden Programm "umgebogen" wurde.
-
- Das beschriebene Verfahren zieht allerdings eine kleine
- Einschränkung nach sich: Wird ein Interrupt durch mehrere
- residente Routinen angezapft, findet MAP immer nur das
- Programm, welches sich als letztes am entsprechenden Vektor "zu
- schaffen machte".
-
- Wie schon angedeutet wird beim Laden eines Programms der Name
- im Environment-Block vermerkt. Wird beim resident machen die
- zugehörige Umgebung nicht berücksichtigt, so hat MAP keine
- allgemein gültige Möglichkeit, den Namen eines Programms zu
- erkennen. Gleiches gilt bei der Verwendung eines DOS mit einer
- Versionsnummer kleiner 3.0. In diesem Fall wird anstelle des
- Programmnamens von MAP ein '???' ausgegeben.
-
- Zum Gebrauch: Man compiliert MAP.PAS am besten als EXE-File.
- Ein Betreiben im Memory-Mode ist im Hinblick auf den
- Verwendungszweck des Programms wenig sinnvoll. Da das Programm
- ohne das Unit CRT auskommt, läuft der Output über die
- Standardausgabe von DOS, kann also beliebig in Drucker, Datei,
- etc. umgeleitet werden.
-
- Die von den TSR-Programmen aufgebauten Interrupt- ketten lassen
- im Grunde nur ,,fein sicheresKonzept für das Entfernen dieser
- Programme zu: Den MARK- RELEASE- Mechanismus, ein Konzept, das
- auch für die Heap-Verwaltung unter Turbo Pascal verwendet wird.
- Die Vorgehensweise ist genauso simpel wie zuverläs- sig, indem
- in einer linearen Liste eine Position mit MARK markiert wird.
- Ein anschließendes RELEASE veranlaßt, daß alle auf diese
- gekennzeichnete Position folgenden Listenelemente bis zum
- Listenende gelöscht und der von ihnen belegte Speicherplatz
- wieder freigegeben wird.
-
- Befinden sich in der Liste mehrere MARKierte Positio- nen, so
- orientiert sich RELEASE am jeweils letzten MARK. Wird jedes an
- die Liste angehängte Element also vorher mit einem MARK
- versehen, so kann man die Liste gezielt von hinten nach vorne
- mittels RELEASE wieder abbauen. Ein Beispiel für die Anwendung
- von MARK- RELEASE zeigt Abbildung 4/5.
-
- Wie kann dieser Mechanismus nun aber konkret als Programm
- umgesetzt werden? Hierzu muß man sich zunächst einmal
- überlegen, was die einzelnen Programmteile leisten müssen.
- Markiert man das Ende der Programm- Liste im RAM und lädt eine
- residente Routine, die man nach Gebrauch wieder entfernen
- möchte , so müssen eigentlich nur die Interruptvektoren nach
- dem RELEASE-Befehl wieder auf dem Stand sein, auf dem sie zum
- Zeitpunkt der Ausführung von MARK waren.
-
- Das Programm, das die RAM-residenten Programme markiert, ist
- praktischerweise selbst resident.
-
- Die einzige Aufgabe von MARK ist es also, die augen- blickliche
- Programm-Ladeadresse und den aktuellen Stand der
- Interruptvektoren irgendwo festzuhalten. Das läßt sich sehr
- elegant bewerkstelligen, indem MARK selbst resident auslegt
- wird. Zum einen lassen sich markierte Stellen so leicht mit dem
- MAP- Programm erkennen, zum anderen braucht man sich keine
- Gedanken zu machen, ob die Interruptvektoren auf einem Laufwerk
- oder sonstwo abgelegt werden sollen: Für sie wird einfach ein
- entsprechendes Plätzchen im MARK-Programmcode reserviert.
-
- Ein Großteil der von RELEASE zu leistenden Arbeit steckt schon
- in dem von MAP verwendeten Include-File MAKEMAP, nämlich das
- Erstellen der Speicherliste. Da diese Liste vorsorglich als
- doppelt verkettet aufge- baut wurde, d.h.von jedem Element mit
- Ausnahme des ersten und letzten kann der Nachfolger bzw.
- Vorgänger erreicht werden, muß RELEASE sich lediglich bis zum
- letzten Listenelement durcharbeiten, um dann die Liste von
- hinten nach vorne aufzurollen, bis das erste Mal ein MARK
- auftaucht. Die alten Interruptvek- toren können nun wieder
- ausgelesen und an ihren ursprünglichen Platz gebracht werden
- und alle Umbie- ge- und Anzapfaktionen der danach geladenen
- Programme sind damit außer Kraft gesetzt.
-
- Natürlich soll auch der von diesen Programmen belegte Speicher
- wieder für andere Zwecke zur Verfügung gestellt werden. Hierbei
- ist die DOS-Funktion 49h (FREE ALLOCATED MEMORY) behilflich.
- Nacheinander werden dieser Funktion alle Ladesegmente der nach
- MARK geladenen Programme übergeben und so wieder freigemacht.
-
- Damit auch noch 2.x-DOS-Anwender in den MARK- RELEASE-Genuß
- kommen, muß eine Erkennung von MARK gewählt werden, die sich
- nicht auf den Namen bezieht, da bei diesen Systemen ja noch
- keine Programmnamen vermerkt werden. Dazu sollte es aber schon
- ausreichen, die ersten Bytes des jeweiligen Programmcodes mit
- denen von MARK zu vergleichen.
-
- Dank der Verwendung von MAKEMAP kann RELEASE ziemlich kurz
- gehalten werden. Auch RELEASE ist nur als EXE- File zu
- betreiben: Ein Lauf im Memory-Mode schickt den Rechner
- unweigerlich in die ewigen Jagdgründe.
-
- Um den Code des residenten Markierungs-Programmes möglichst
- klein zu halten, hilft ein Trick aus alten Zeiten: Ein "Lader"
-
- Einiges Kopfzerbrechen bereitet zunächst das MARK- Programm: Da
- diese Routine wahrscheinlich des öfteren in den Speicher
- geladen wird, im Extremfall vor jedem residenten Programm, ist
- es natürlich günstig, den Programmcode von MARK so klein wie
- möglich zu halten.
-
- Da der in MARK benötigte Code im Grunde genommen ver-
- schwindend klein ist, denn es muß ja nur das Kopieren der
- Interruptvektoren vorgenommen werden, wurde zu einer Methode
- gegriffen, die einige unter den Lesern vielleicht noch aus
- ihren Anfängen kennen: In Anlehnung an die berühmt-
- berüchtigten BASIC-Lader wird das MARK-Programm von einem
- "Turbo-Lader" erzeugt. Der eigentliche Programmcode taucht im
- Laderprogramm MAKEMARK als Array of Byte auf und wird als
- ausführbares COM-File auf Diskette geschrieben, so belegt er
- lediglich 23 Bytes auf Diskette und mit der Interrupt-Tabelle
- ca. 1,4 kByte resident im Speicher!