|
Bild 5 Das Doppelleben des Turbo-Debuggers:
Auf Maschinenebene ...
Bild 6 ... und im Hochsprachenlook
|
|
Uwe Schulze, Berlin
Debugger
– Werkzeug für schlechte Programmierer?
Auch wenn die Überlieferung, der Begriff Debugger (bug, englisch: Wanze) rühre von einem Insekt her, das mit seiner Anwesenheit zwischen den Relaiskontakten eines Großrechners diesen außer Betrieb gesetzt hat, wohl nicht authentisch ist, so umreißt der heute ausschließlich auf Software bezogene Begriff doch das Ziel: Die Beseitigung heimtückischer, schwer zu lokalisierender, logischer Fehler.
"Richtige" Programmierer sind zwar häufig der Meinung, keine Fehler zu begehen oder diese durch logische Überlegung zu finden, nichtsdestotrotz kann ein Debugger ein sehr effizientes Werkzeug sein, um komplizierten Fehlern schnell auf den Grund zu gehen. Denken Sie nur an Assemblerprogramme oder die Nebeneffekte in Hochsprachen. Das darf natürlich nicht darüber hinwegtäuschen, daß Fehlern am besten vorgebeugt wird, wenn gut strukturiert nach einem sorgfältigen Entwurf Modul für Modul programmiert und getestet wird.
Die Idee des Debugging besteht in der Beobachtung des Programms während der Abarbeitung. Diese Überwachung bezieht sich auf den Programmablauf (Sprünge, Unterprogrammrufe) und die aktuelle Belegung der Daten. Es ist leicht zu verstehen, daß das für eine Hochsprache recht kompliziert ist und wegen der unterschiedlichen internen Darstellung für jeden Compiler ein passender Debugger benötigt wird. Nur ein Beispiel ist die unterschiedliche Realzahl-Darstellung.
Debuggen auf Maschinenebene
Die ersten PC-Debugger waren wenig komfortabel und gestatteten nur die Arbeit auf Maschinenebene. Deshalb dienten sie auch
in erster Linie zur Unterstützung von Assemblerentwicklungen. Der Standarddebugger für CP/M war ZSID (Zilog Symbolic Instruction Debugger), zum Lieferumfang von MS-/PC-DOS (kurz: DOS) gehört das Programm Debug. Im Mittelpunkt der Arbeit eines Debugger steht der Trace-Befehl. Damit können Programme im Einzelschrittbetrieb abgearbeitet werden. Mit
t = 100 5
werden mit Debug 5 Assemblerbefehle ab der Adresse 100 ausgeführt und jeweils die Register angezeigt, wodurch der Programmverlauf (Verzweigungen und Datenbelegung) überwacht werden kann. Um Schleifen nicht in Einzelschritten durchlaufen zu müssen, gibt es die Möglichkeit, Unterbrechungspunkte (Breakpoints) zu setzen, die das Programm an entsprechender Stelle stoppen. Ein direktes Ansehen von Datenbereichen in hexadezimaler Form kann mit dem Kommando Dump erfolgen, beispielsweise dient
d 100 110
zur Anzeige des Speicherbereiches von Adresse 100 bis 110 (bezogen auf das
Datensegmentregister, wenn nicht anders angegeben). Um aber die Zuordnung der
Programmkonstrukte zu den aktuell belegten Speicherplätzen zu erhalten, benötigt der Programmierer ein List-File, das vom Assembler erzeugt werden kann. Hier werden auch die Grenzen dieser Art von Arbeit sichtbar: Komplexe Programme lassen sich so kaum verfolgen. Eine wertvolle Option des Debuggers ist das Assemblieren. Damit können kurze Assemblerstücke in Assemblermnemonik eingegeben werden. Mehr dazu jedoch später. Ebenso wird das interaktive
Reassemblieren unterstützt.
Weitere nützliche Funktionen eines Debuggers sind eine einfache
Hexadezimal-Arithmetik (vor allem zur Adreßrechnung), sowie Füll-, Vergleichs-, Verschiebe- und Suchoperationen im Speicher.
Symbolisches Debugging
Der nächste Schritt ist die Nutzung von Symbolen des Quelltextes für die Fehlersuche. Bereits der erwähnte Debugger ZSID bietet diese Möglichkeit. Für DOS kann der Standarddebugger Symdeb verwendet werden, der mit dem Assemblerpaket geliefert wird. Der Programmierer wird der Aufgabe enthoben, mit den konkreten Adressen zu operieren. Statt dessen können
Label-, Segment-, Prozedur- und Variablennamen direkt angegeben werden. Die Verbindung wird über ein Sym-File hergestellt, das beim Linken angelegt wird. Dazu muß die Assemblierung mit folgender Kommandofolge abgewickelt werden:
1. Alle Symbole als public deklarieren
2. Assemblieren: masm test,,;
3. Linken und Map-Datei erzeugen: link test,,/map;
4. Erzeugen Symboldatei: mapsym test
5. Starten des Debuggers: symdeb tes.sym test.exe
Es können auch mehrere Sym-Dateien geladen werden.
Um sich jetzt einen 16-Bit-Wert anzusehen, der an der Marke Wert steht, reicht der Befehl
dw ds:wert
DW steht für Dump Word und DS kennzeichnet das Datensegment. Tafel 1 enthält eine Kommandoübersicht von Symdeb. Die neue Qualität von Symdeb zeigt sich auch in der Nutzung verschiedener Bildschirmseiten für Testprogramm
und Debugger (damit die Ausschriften des Debuggers nicht das Bild des Testprogrammes zerstören), Möglichkeiten der getrennten Ein-/Ausgabeumleitung für den Debugger mit < und > und das Testprogramm mit { und } sowie in der Berechnung arithmetischer Ausdrücke.
Praktisch gegenüber Debug ist ferner die Möglichkeit, sich Speicherbereiche in verschiedenen Formaten anzeigen zu lassen (Dump). So kann man sich den Interruptvektor beispielsweise mit DD (für Dump
Doubleword) im Adreßformat ansehen. Der entsprechende Befehl dazu heißt
dd 0:0
und erleichtert die Lesbarkeit der bei Intel-Prozessoren üblichen
Highteil-/Lowteil-Darstellung (siehe Bild 1). Die Eingabeumleitung wird oft dazu benutzt, kleine Assemblerprogramme mit dem Debugger zu erstellen, ohne auf einen Editor zu verzichten. Beispielsweise läßt sich folgende Befehlsfolge mit einem beliebigen Editor als Datei Bell.asm
erstellen:
Ahnen Sie, was das Programm macht? Wie der Name schon sagt ...
– aber probieren Sie es doch selbst. Achten Sie dabei bitte auf die Leerzeile in der 7. Zeile. Der Aufruf
symdeb < bell.asm
erzeugt ein Programm Bell.com, das man starten kann – und das alles ohne Assembler und Linker. Der gleiche Effekt wird aber auch erzielt, wenn die Befehlsfolge interaktiv in Symdeb eingegeben wird. Zu beachten ist allerdings die geringfügig andere Assemblernotation: Die Angabe des Segmentpräfixes erfolgt mit cs: mov ax,[di] statt mov ax,cs:[di], und die Größe unbestimmter Operanden kann mit inc byte [0815] bzw. ince word [0815] angegeben werden.
Die Nutzung verschiedener Bildschirmseiten dient vor allem dazu, auch Programme testen zu können, die mit ihren Ausgaben den gesamten Bildschirm in Anspruch nehmen oder im Grafikmodus arbeiten. Dazu muß Symdeb mit dem Schalter /s gestartet werden. Mit dem Backslash (\) kann umgeschaltet werden. Ein weiterer nützlicher Schalter ist /k. Er erlaubt den Abbruch von Endlosschleifen mit <Ctrl>-C (^C). Das ist mit Break on im Betriebssystem nicht zu erreichen, da damit nur Systemrufe überprüft werden. Enthält die Programmschleife keine BDOS-Rufe, so wäre ein Abbruch nicht möglich. Wird allerdings gerade auf eine Eingabe gewartet, kann stets mit ^C abgebrochen werden. Ferner ist Symdeb für die Hochsprachenunterstützung ausgelegt. So kann man beispielsweise Daten im Real-Format dumpen
– allerdings müssen sie dem lEEE-Format entsprechen, also 4, 8 oder 10 Byte lang sein. Borlands eigenwilliges 6-Byte-Format bei Turbo-Pascal 3.0 wird also nicht bedient. Statt dessen wollen wir uns ansehen, wie man Programme ab Version 4.0 mit Symdeb symbolisch debuggen kann
– nur als Beispiel, denn nötig hat man es angesichts der neuen Möglichkeiten eigentlich nicht mehr. In der integrierten Entwicklungsumgebung von Turbo-Pascal ist dazu der Schalter Options/Linker/Map File auf Detailed zu setzen, beim Kommandozeilencompiler der Schalter /GD. Während der Übersetzung wird jetzt ein Map-File angelegt. Es handelt sich um ein Textfile, das die Zuordnung der Bezeichner zu den Adressen enthält und das man sich mit einem Editor ansehen kann. Das Programm Mapsym wandelt das Map-File in ein Sym-File um, wie es von Symdeb verwendet wird:
mapsym test
Dieses kann folgendermaßen in den Debugger geladen werden:
symdeb test.sym test.exe
Der Debugger zeigt beim Kommando u (Unassemble) Pascal- und Maschinenbefehle gemischt an. An Stelle der Adressen können die Variablen- bzw. Prozedurnamen angegeben werden.
Moderne Nutzeroberflächen machen vor Debuggern nicht halt. Microsoft stellte mit
Codeview den ersten Fullscreen-Debugger vor – für Symdeb-Umsteiger befehlskompatibel. So ist es möglich, den Quellcode, die Registerbelegung und mehrere Speicherbereiche als Dump gleichzeitig in verschiedenen Fenstern zu beobachten (siehe Bild 2). Auch die Maus kann benutzt werden. Allerdings wird der erhöhte Komfort auch mit größerem Einarbeitungsaufwand bezahlt, so daß
Gelegenheits-Bugjäger ihn wohl kaum benutzen werden. Tafel 2 zeigt die
Funktionstastenbelegung; wie Codeview gestartet wird, läßt sich bei Hübener, J.: MS-DOS, Verlag Technik, Berlin 1989, S. 183 nachlesen.
Codeview unterstützt auch die Microsoft-Hochsprachen (Fortran, Basic und C; neuere Versionen auch Pascal). Hier wird aber ein anderer Weg gegangen als bei Borland, wo sich der Debugger stets ein gleichnamiges Quellfile sucht. Durch Setzen des Schalters /zi beim Compilieren bzw. Assemblieren werden Zeilennummern und Quellcode in das Objektfile eingefügt, beim Linken ist Schalter /co zu verwenden. Das erzeugte Exe-File enthält jetzt auch den Quelltext und Codeview benötigt nur das Exe-File, um auf Hochsprachenniveau zu arbeiten. Das fehlerfreie Programm ist dann noch einmal ohne den entsprechenden Schalter zu linken, damit der Quellcode nicht zugänglich ist.
Voraussetzung für Quellcodeunterstützung ist ein Linker ab Version 3.6 aus dem MASM-5.0-Paket. Sollen so vorbereitete Programme mit dem Turbo-Debugger bearbeitet werden, so muß das dort mitgelieferte Utility Tdconvrt, verwendet werden. Die neuen Quick-Compiler von Microsoft warten inzwischen auch mit integrierten Debuggern auf.
Neben Codeview existieren noch eine ganze Reihe anderer Fullscreen-Debugger, die bestimmte Vorzüge besitzen und sich größtenteils auf das Microsoft-Sym-Format stützen. Sehr nutzerfreundlich präsentiert sich AFD (Advanced Fullscreen Debugger). Ähnlich wie bei Codeview werden das Programm, die Register und zwei Dump-Bereiche gleichzeitig dargestellt (Bild 3). Insbesondere das
Abspeichern von Breakpoints und die Nutzung von Schleifenzählern zum Abbruch nach einer bestimmten Anzahl von Durchläufen erleichtern die Arbeit (Bild 4). Eine weitere Hilfe ist das Speichern von Befehlsfolgen zur wiederholten Abarbeitung. Das kann entweder durch Erstellen der Befehle mit einem Editor erfolgen (Befehlsübersicht siehe Tafel 3), oder durch Einschalten des Teach-in-Modus, der alle abgearbeiteten Kommandos speichert. Beispielsweise wird die Kommandofolge
KX1 testafd
m 1 ds:100
r cx=0815
in der Datei Auto.dat automatisch abgearbeitet, wenn AFD mit
afd "XX auto.dat
gestartet wird. Sie bewirkt, daß das Pro gramm Testafd geladen, in Dump-Fenster 1 die Adresse ds:100 eingestellt und das Register cx mit dem Wert 0815 geladen wird. Die Buchstaben KX am Anfang sind eine Kennung.
Bei neueren Versionen ist sogar die Einbindung eigener Befehle möglich /4/. Beim Start läßt sich ein Interrupt festlegen, der angesprungen wird, wenn AFD einen unbekannten Befehl erkennt, beispielsweise
afd /U60
für Interrupt 60H. Ein dort installiertes eigenes Programm kann die neuen Befehle bearbeiten; ein Zeiger auf den Befehl wird in den Registern DS:SI übergeben. Die Interrupts 60H bis 65H sind für derartige Anwendungen von DOS freigehalten.
Ein anderer Fullscreen-Debugger ist
Periscope. Er unterstützt als einer der ganz wenigen (neben dem noch zu besprechenden Turbo-Debugger) auch die Register des Arithmetik-Koprozessors und läßt sich ebenfalls gut zum Testen von Turbo-Programmen verwenden.
Eine ganz ausgeklügelte Hilfe ist die Verwendung zusätzlicher Hardware durch einige Debugger. Dabei befindet er sich auf einer zusätzlichen Karte mit eigenem Prozessor und eigenem RAM. Somit können ohne Absturz auch diffizilste Betriebssystemsroutinen getestet werden, da das Debugger-Programm nicht auf das Betriebssystem angewiesen ist.
Source-Level-Debugging
Es ist leicht vorstellbar, daß das beschriebene Verfahren der Programmentwicklung auf Maschinenebene moderne Hochsprachen mit komplexen Daten- und Programmstrukturen sowie teilweise recht großen Bibliotheken nur unzureichend unterstützt. Der Programmierer benötigt Informationen über die interne Darstellung der Daten, Parametervermittlung und Bibliotheksaufbau. Deshalb liegt der Gedanke nahe, direkt auf Ebene des Quellcodes den Programmverlauf und die Variablenbelegung zu beobachten.
Wegbereiter war Turbo-Pascal 5.0 mit dem integrierten Debugger in der Entwicklungsumgebung und separatem Turbo-Debugger, der noch weitergehende Möglichkeiten bietet. Der integrierte Debugger bietet die Möglichkeit der Arbeit im Einzelschrittbetrieb (Hotkey F7). Dabei wird aber nicht ein Maschinenbefehl, sondern jeweils eine Pascal-Anweisung ausgeführt, genaugenommen eine Quelltextzeile. Um Anweisungen einzeln auszuführen, müssen sie auch einzeln auf einer Zeile stehen. Bereits ausgetestete Prozeduren lassen sich auch in einem Schritt ausführen (Hotkey F8). Bibliotheksfunktionen werden stets im Ganzen abgearbeitet, da sie keine
Debug-lnformationen enthalten. Eingegrenzten Fehlern kann man sich gut mit "go to Cursor" (Hotkey F4) nähern. An der Cursorposition wird das Programm gestoppt, um in Einzelschritten weiterzuarbeiten. Eventuelle Ausgaben des Testprogrammes erfolgen
– wie bei Symdeb möglich – generell in eine separate Bildschirmseite, zu der umgeschaltet werden kann.
Wird mit Includes oder Units gearbeitet, so lädt Turbo automatisch die Quelltexte der anderen Programmteile nach, wenn Prozeduren oder Funktionen daraus aufgerufen werden. Erfolgt während der Trace-Schritte eine Veränderung des Quelltextes, so erkennt der Compiler dies und fragt, ob neu übersetzt werden soll. Die Möglichkeit der sofortigen Compilierung nach einer Fehlerkorrektur ist auch der entscheidende Vorteil gegenüber dem
Stand-alone-Debugger. Die Menüs Debug und Break/Watch bieten noch folgende Möglichkeiten (siehe auch MP11/89, S. 325): Setzen und Löschen von Unterbrechungspunkten (Breakpoints), Beobachtung von Variablenbelegungen (Watch), Berechnung und Änderung von Pascal-Ausdrucken (Evaluate) sowie Informationen über die Prozedurhierarchie (Call Stack).
Nicht unterstützt werden dagegen bedingte Unterbrechungspunkte; das Verfolgen von Zeigern ist unkomfortabel, da sie nur als Adressen dargestellt werden.
Sie werden sich fragen, warum neben dem integrierten Debugger noch ein
Stand-alone-Debugger ausgeliefert wird. Aus Speicherplatzgründen konnten nur die wichtigsten und am häufigsten benötigten Funktionen aufgenommen werden. Für weitergehende Aufgaben muß der Turbo-Debugger (der auch für Turbo-C geeignet ist) herangezogen werden. Außerdem unterstützt er den Turbo-Assembler und erlaubt gleichzeitig das
Debugging auf Maschinenebene. Er bietet dem Programmierer seine gewohnte Arbeitsumgebung, dazu gehören die bewährten Menüs, kontextbezogene Hilfe und die Zahlendarstellung im Format der jeweiligen Sprache ($4711 bei Pascalprogrammen bzw. 0x4711 in C). Ein Fenster mit den Maschinenbefehlen, den Registern und dem Dump oder mit dem Quelltext ist stets präsent, weitere können vom Nutzer beliebig geöffnet und angeordnet werden (weitere Dumps, Variablenbelegungen, Breakpoints, Koprozessor-Register und vieles mehr). Die Bilder 5 und 6 geben einen kleinen Einblick.
Um ein Programm mit Informationen für das Stand-alone-Debugging zu versorgen, muß in der integrierten Entwicklungsumgebung die Option Debug/Stand Alone auf On gesetzt werden bzw. der Schalter /v des Kommandozeilencompilers TPC angegeben werden, also
TPC test /v
Die Programme werden dadurch erheblich größer (15 KByte statt 9 KByte bei einem Testprogramm). Nach erfolgreichem Test können diese Informationen aber wieder entfernt werden, da sie sich am Ende des Files befinden. Um nicht neu übersetzen zu müssen, stellt Borland das Programm Tdstrip zur Verfügung.
Der Turbo-Debugger nutzt nicht das Quasi-Standard-Format von Microsoft. Um trotzdem solche Programme debuggen zu können, bietet Borland das Programm Tdmap an, mit dem von Standard-Linkern erzeugte Map-Dateien (siehe oben) im Turbo-Format an das Exe-File angehängt werden. An dieser Stelle sei auch erwähnt, daß der Turbo-Linker mit dem Schalter /t direkt Com-Files erzeugt und damit Exe2bin überflüssig macht.
Der Turbo-Debugger bietet alles, was dem integrierten Debugger noch fehlt, beliebige bedingte und unbedingte Breakpoints, Abbruch auf Tastendruck sowie Unterstützung des Arithmetik-Koprozessors. Daneben gibt es zwei Optionen zur Unterstützung, sich wiederholender Einstellungen, wie sie bei mehreren Testumläufen auftreten: History Lists und Makros. Ähnlich den bereits bekannten Pick-Listen beim Laden von Files merkt sich der Debugger die zuletzt vorgenommenen Eingaben in den einzelnen Menüs. Sie können mit den Cursortasten wiederholt ausgewählt werden. Wenn mit Tdinst nichts anderes festgelegt ist, so werden die letzten zehn Eingaben festgehalten. Makros enthalten wiederholte Befehlsfolgen, aber auch Einstellungen von Bildschirmfenstern, Setzen von Breakpoints u. ä. Beliebige Makros können auf beliebige Tasten gelegt werden. Das Anlegen, Löschen und Starten von Macros erfolgt im Menü Options/Macros. Um ein neues Makro zu definieren, wird in einen Lernmodus (Teach in) geschaltet, der alle Nutzeraktionen speichert. Auf Tastendruck sind sie jederzeit wieder aufrufbar. Der Turbo-Debugger präsentiert sich auf der Höhe der Zeit. Er unterstützt den i80386, indem er Programmen eine virtuelle 8086-Task zur Verfügung stellt. Man muß dazu TD386 starten. Etwas kleiner geht es auch über die serielle Schnittstelle. So kann der Debugger auf einem zweiten Rechner laufen und ermöglicht auch das Testen großer Programme. Nötig sind die beiden Programme Tdremote und Tdrf. Es können Übertragungsraten bis zu 115000 Baud eingestellt werden. Weiterhin kann er mit EMS umgehen bzw. dessen Emulation auf einem 286er nutzen.
Die Version 1.5 des Turbo-Debuggers unterstützt jetzt auch die objektorientierten Möglichkeiten des Compilers Turbo-Pascal 5.5 (siehe MP 2/90 S. 44).
Literatur
/1/ IBM: DiskOperating System, Technical Reference 1984
/2/ Heimsoeth Software GmbH & Co Produktions- und Vertriebs-KG: Handbuch Turbo-Pascal, Version 5.0, München, 1988
/3/ Borland International: Turbo Debugger, User's Guide Version 1.0, Scotts Valley 1988
/4/ Bäumler, D.: Die AFD-Pro-Werkstatt, Assembler-Programmierung von Anfang an. DOS Extra (1989) 8
/5/ Strauss, P.: Moderner PC-Assembler: MASM 5.0 zeigt, was er kann, mc (1989) 5, Franzis Verlag, München
|
|
|
|
|
Uwe Schulze, Berlin
kennengelernt:
JPI TopSpeed Modula-2
Nach seinem guten Abschneiden beim Compiler-Wettlauf in MP 4/90 verdient es der TopSpeed Modula Compiler, einmal genauer vorgestellt zu werden. Dabei geht es weniger um die Sprache Modula, als vielmehr um die Qualitäten des Compilers und der Entwicklungsumgebung.
Die Entwicklungsumgebung
In vielem knüpft JPI Modula an die guten Eigenschaften von Turbo-Pascal an. Kein Wunder: Die Firma Jensen & Partners International (nichts anderes heißt JPI) wurde von ehemaligen Borland-Programmierern in England gegründet. Und in der Geschwindigkeit hat man das Vorbildprodukt bereits übertroffen. Die Menütechnik erinnert durchaus an Borland-Produkte (Menübäume statt Dialogboxen wie bei Microsoft), darüber hinaus können die Menüs aber völlig frei konfiguriert werden. Das betrifft natürlich die Farben, die ebenso interaktiv zu jedem beliebigen Zeitpunkt (bei Turbo nur mit TINST) geändert werden können wie die Anordnung auf dem Bildschirm. Das Hauptmenü im Bild oben habe ich in die rechte obere Ecke gerückt, damit es den Quelltext nicht verdeckt
– ursprünglich stand es links. Darüber hinaus lassen sich aber auch die einzelnen Menüpunkte und die Hotkeys festlegen. Verantwortlich dafür ist das Menüfile M2.MNU, von dem ein Ausschnitt im Bild darunter dargestellt ist. Durch Einrücken erfolgt automatisch die Zuordnung zu Untermenüs, die Optionen Load Files, Pick Files usw. bilden also ein Untermenü von Files. Dieser Menüaufwand wird dann (im oberen Bild) rechts zu erkennen sein. Der Buchstabe in geschweiften Klammern wird später hervorgehoben dargestellt (heller oder andersfarbig) und kann im entsprechenden Menü zur direkten Aktivierung dieses Punktes verwendet werden (als Alternative zur Bewegung des Farbbalkens mit den Cursortasten). In spitzen Klammern sind die Shortcuts festgelegt. Mit einem einfachen Editor kann so die gesamte Nutzeroberfläche geändert werden. Die Fehlermeldungen in einem extra ASCII-File zu halten gehörte schon bei Turbo 3.0 zum guten Ton, auch die Online-Hilfe ist inzwischen selbstverständlich.
Dem Programmierer steht ein Multi-Window-Editor (Wordstar-kompatibel, aber auch beliebig anders einzurichten) zur Verfügung, mit dem bis zu vier Dateien gleichzeitig bearbeitet werden können (siehe Bild 1). Beim Verlassen der Entwicklungsumgebung werden nicht nur die gerade geladenen Quelltexte, sondern auch die aktuelle Cursorposition, geöffnete Fenster etc. in ein sogenanntes
Session-File gespeichert, das es ermöglicht, genau an der Stelle weiterzumachen, wo man beim letzten Mal aufgehört hat. Die Auto-Save-Option garantiert, daß vor dem Lauf eines Programms (und dem damit möglichen Absturz) sowie beim Verlassen stets alle geänderten Quelltexte gesichert werden, was insbesondere bei mehreren gleichzeitig in Bearbeitung befindlichen Texten von Bedeutung ist.
Eine weitere nützliche Einrichtung ist das Redirection File, mit dem sich der Compiler sein eigenes Environment anlegt. Damit werden nicht nur getrennte Directories für Quelltexte, Bibliotheken, Objete etc. festgelegt; es kann auch genutzt werden, um lokale Festlegungen im Netzbetrieb zu treffen.
Der Compiler
Compiler und Linker können wahlweise aus der integrierten Entwicklungsumgebung oder als Kommandozeile aufgerufen werden, ohne daß dafür ein extra Programm nötig wäre (wie TPC bei Turbo-Pascal); es genügt die Angabe eines Schalters. Die Übersetzung der
Implementationsteile kann in beliebiger Reihenfolge vorgenommen werden, unaktuelle Definitionsmodule gibt es nicht, da sie stets neu compiliert werden
– die Geschwindigkeit des Compilers (der Hersteller gibt 20000 Zeilen pro Minute an) läßt das zu. Gleichzeitig entfallen die Symbol-Files, weil die Definitionsmodule direkt ins Programm übersetzt werden. Große Projekte werden durch die Make-Funktion unterstützt. Der Compiler erzeugt in einem Paß Microsoft-kompatiblen Objektcode
– angesichts der großen Geschwindigkeit eine erstaunliche Leistung. Der Programmierer besitzt damit eine Schnittstelle zu anderen Sprachen, auch zum Assembler. Voraussetzung ist aber, die Definition der anderssprachigen Module in einem Modula-DEF-File aufzuführen und beim Linken die richtige Reihenfolge der Objektmodule einzuhalten.
Der Linker arbeitet – wie an der Codegröße erkennbar und von Turbo-Pascal gewöhnt
– intelligent, das heißt, er entfernt automatisch nicht aufgerufene Funktionen. Außerdem genügt beim Linken die Angabe des Hauptmoduls, der Informationen über alle weiteren benötigten Objekte (in einem Include-Record) und die erforderliche Aktualität (in einem Version-Record) enthält.
Bei Nutzung des Microsoft-Linkers zur Einbindung fremder Objekte werden wesentlich größere EXE-Files erzeugt, und alle Files müssen explizit und in der richtigen Reihenfolge angegeben werden.
In zwei getrennten Bibliotheksmodulen sind zum einen der Sprachstandard nach Wirth und zum anderen die pragmatischen Erweiterungen von JPI implementiert. Obwohl zur Sprache Modula gehörend, wird
Coprocessing nicht von allen Modula Compilern auch wirklich angeboten. JPI offeriert hier einen
Time-Slice-Scheduler für echtes Multitasking. Die OS/2-Version setzt im Protected Mode
Koprozesse in separate OS/2-Threads um. Leider gibt es für MS-DOS keinen Schalter zur Nutzung der Vorzüge des 80286. Der
Arithmetik-Koprozessor i8087 wird unterstützt und – wenn nicht vorhanden
– stets emuliert.
Die Geschwindigkeit der Programme ist beeindruckend und liegt in Bereichen, die man sonst nur C-Compilern zugetraut hätte (siehe /1/). Sie wird durch eine ausgefeilte Optimierung (z. B. Registervergabe) erreicht.
Gut unterstützt JPI – und das sei extra erwähnt, weil mit diesem Argument häufig eine Lanze für C gebrochen wird
– die hardwarenahe Programmierung. Vieles ist von Turbo bekannt: Der Aufruf von DOS- und BIOS-Funktionen, der direkte Zugriff auf Speicherzellen und Ports sowie die Erzwingung von FAR-Sprüngen zur Einbindung externer Programmteile. Darüber hinaus existieren beim TopSpeed-Compiler Schalter, mit denen festgelegt werden kann, welche Register bei Eintritt in eine Prozedur gerettet werden sollen, ob mit RET oder IRET beendet wird, welcher Programmcode stets zu Beginn und am Ende einer Prozedur eingefügt werden soll (wie für
MS-Windows-Applikationen gefordert) bzw. ob statt dessen nutzereigene Interrupts angesprungen werden sollen (zum Tracen nutzbar).
Für konkurrierende Prozesse kann es nötig sein, die Optimierung des Gebrauchs von Variablen abzuschalten, die automatisch so lange wie möglich in Registern gehalten werden (keine Speicherklasse REGISTER wie in C nötig), was unter Umständen bedeutet, daß eine Speicherzelle im gemeinsamen Zugriff nicht aktuell ist. Per Schalter kann das Auslagern in den Speicher nach jeder Operation erzwungen werden.
Über die Annehmlichkeiten von Turbo-Pascal hinaus – die man fast sämtlich findet
– sind mir noch Funktionen zur Adreßrechnung (AddAddr, IncAddr), zum Sperren der Hardwareinterrupts (DI, El)
– wofür man in Turbo Inlines bemühen muß – und eine gute Mathematik-Bibliothek aufgefallen. Den professionellen Window-Modul findet man sonst nur in Toolboxen.
Die mitgelieferten Bibliotheken und Tools sind nicht so umfangreich wie beim Logitech-Compiler, aber eigentlich bleiben keine Wünsche offen. Im einzelnen besteht die Bibliothek aus 12 Modulen (plus SYSTEM), deren Namen aber
– ebenso wie die vieler Prozeduren – vom Standard abweichen (z. B. IO statt InOut). Im Überblick: siehe in der
linken Spalte.
Extra geliefert wird ein sogenanntes TechKit, das die Assembler-Quellen der Run-Time-Bibliothek und den TopSpeed-Assembler enthält. Seine Mnemonik weicht aber vom
Microsoft-quasi-Standard ab. Er ist einfach gehalten, unterstützt keine Macros etc. Daß aber Kommentare in
Modula-Notation angegeben werden müssen – (* und *) –, das Semikolon dafür aber zur Trennung mehrerer Befehle auf einer Zeile vergeben ist, läßt die Übernahme von Assemblerquellen kaum zu.
Ein nützliches Tool ist das Programm ANALYZE, das die Abhängigkeiten und die Aktualität der einzelnen
Module zeigt:
Weiterhin im TechKit enthalten sind die Module zur Unterstützung residenter Programme, der seriellen Schnittstelle und von Expanded Memory.
Ein neuer Gedanke ist die sogenannte TechLine. Damit können Sie aus der Entwicklungsumgebung heraus über ein Modem die Entwickler in London direkt an die Leitung holen
...
Literatur
/1/ Schulze, U.: Im Test: Compiler für MS-DOS. Mikroprozessortechnik, Berlin 4 (1990) 4, S.103
/2/ TopSpeed Modula-2 TechKid. Jensen & Partners International 1988
/3/ Die TopSpeed-Story. Toolbox (1989) 6, S. 8
/4/ Braun, M.; Guther, J.: Modula-2 wird erwachsen, mc, München (1988) 9, S. 68
/5/ Hauptmann, S.: Modula-2: Pascal ohne die Nachteile von Pascal. Mikroprozessortechnik, Berlin 2 (1988) 10, S. 296
/6/ JPI TopSpeed Modula-2 Benutzerhandbuch, Jensen & Partners International and ALISYS 1988
|
|