*******************************************************************************  K I C K - A S S  Das besondere  Assembler Editor Monitor Linker Debugger Tracer  System für den AMIGA  Version 1.95  Copyright, Vertrieb, Support:  MAXON Computer GmbH Kennwort: KICK-ASS Postfach 55 69 6236 Eschborn  *******************************************************************************  Die folgenden Texte sind Ergänzungen zu der UPGRADE-Version 1.95:  (* Ergänzung zu Kapitel 1 *)  TRACE Diese Directive erzeugt den illegalen Opcode $ABCE. Der Exception-Handler schaltet den Prozessor dann in den Trace-Modus. Alles weitere erfahren Sie im Kapitel "Debugger". TROFF ("TRace OFF") erzeugt den Code $ABCF, bei dem der Exceptionhandler automatisch den Trace-Modus ausschaltet. Auch hierzu steht alles weitere im Debugger-Kapitel. ORG adr legt die Startadresse des zu erzeugenden Objekt-Codes fest. Im allgemeinen ist es auf dem Amiga nicht sinnvoll, Programme auf einen bestimmten Adreßbereich festzulegen, da man nie weiß, wohin ein Programm vom Betriebssystem geladen wird. Deshalb erzeugt Kick-Ass auch normaler- weise relokierbaren Code, d.h. der Assembler merkt sich, an welchen Stellen das Programm später an den jeweiligen Adreßbereich angepaßt werden muß und hält sie in der sog. Relokationstabelle fest. Es gibt jedoch auch Ausnahmefälle, in denen Maschinen-Code für einen bestimmten Speicherbereich benötigt wird, z.B. bei den allseits beliebten (und als Viren gefürchteten) Bootblock-Programmen, oder wenn man sich das Programm auf ein EPROM brennen will. Für solche Fälle ist die ORG-Directive gedacht. ORG muß nur bei Bedarf an (höchstens einer!) beliebigen Stelle im Programm gesetzt werden und teilt dem Assembler mit, welche absolute AnfangsAdresse für das Programm gewünscht wird. Das hat zunächst jedoch keine weitern Folgen, denn der Assembler beschränkt sich darauf, die Adresse auf Plausiblität zu prüfen und sie sich zu merken. Mit dem Monitorbefehl "WC" können Sie sich dann den auf diese Adresse angepaßten Code in eine Datei schreiben lassen. DATA, BSS und CHIP Das Amiga-Betriebssystem sieht die Möglichkeit vor, ein Programm in mehrere Teile, die sogenannten "Hunks", aufzuteilen. Wenn das Programm dann später in den Arbeitsspeicher geladen wird, fügt das AmigaDos die Hunks wieder zusammen. Mit Kick-Ass können Sie Ihr Programm in bis zu vier Hunks aufteilen: 1. CODE Dieser Hunk ist immer vorhanden. Er ist der einzige, der ausführbaren Code enthalten darf, während die anderen Hunk-Typen nur Daten aufnehmen können. 2. DATA In diesem Hunk, der mit der gleichlautenden Directive eingeleitet wird, können nur Daten stehen, die mit den Directives DC und BLK erzeugt werden. Über den Sinn eines solchen Hunks läßt sich streiten, denn Sie können diese Daten natürlich genauso gut im CHIP-Bereich unterbringen. Zudem verlängert jeder zusätzliche Hunk die Programmdatei, und über Hunkgrenzen hinweg können Adressen nicht mit der sehr effektiven PC-relativen Adressierungsart ange- sprochen werden. 3. CHIP Der Amiga unterscheidet ärgerlicherweise zwei Arten von Speicher: das Chip- und das Fastmemory. Die Customchips Agnus, Denise und Paula können nur auf das Chipmemory zugreifen, das im allgemeinen die untersten 512 kByte des Adreßraums umfaßt (Adressen von $000000 bis $07ffff einschließlich). Hier müssen Sie alle Daten ablegen, auf die die Customchips per DMA zu- greifen müssen, z.B. Bilddaten für Denise, Sound-Daten für Paula oder die Programme für den Co-Prozessor Copper. Auch die eigentlichen Bilddaten der Intuition-Struktur IMAGE müssen in diesem Speicherbereich liegen, damit der Blitter sie in den Bildschirmspeicher kopieren kann. Der Chip-Hunk ist nichts weiter als ein Data-Hunk, der mit einer besonderen Markierung versehen wird, so daß er vom Betriebssystem automatisch ins Chip-RAM geladen wird. Wenn Sie ein Programm aus der Entwicklungsumgebung von Kick-Ass starten, wird der Chip-Hunk zuvor ins Chipmemory kopiert. Disassemblieren sie den von Kick-Ass erzeugten Code, werden Sie feststellen, daß der Assembler die besonderen Bedürfnisse des Chip-Hunks zunächst völlig ignoriert. Erst unmittelbar vor der Programmausführung wird der eventuell vorhandene Chip-Hunk in einen Chipmemory-Breich kopiert und die Adressen werden entsprechend angepaßt. Nach der Programmausführung werden diese Adressen auch sofort wieder zurückgebogen. Der Chip-Hunk ist im Gegensatz zu seinem Data-Bruder unverzichtbar. Auch wenn Sie nur über 512 kByte Speicher verfügen (also nur über Chipmemory), sollten Sie für die entsprechenden Daten immer einen Chip-Hunk einrichten, denn vielleicht wollen Sie ihr Programm ja einmal an jemanden weitergeben, der eine Speichererweiterung (die stets im Fastmemory-Adreßbereich liegt) besitzt. Genau wie im DATA-, dürfen im CHIP-Hunk nur Daten stehen. 4. BSS Dieser Hunk ist eine sehr pfiffige Einrichtung: Fast jedes Assembler-Programm reserviert mit sich BLK.x Speicher, der zum Speichern von Daten dient und beim Programmstart noch keinen definierten Inhalt haben muß. Es wäre nun unnötig, im Programm-File auf der Diskette (oder Harddisk oder so...) ent- sprechend viele Bytes zu belegen. Der BSS-Hunk besteht im Loadfile nur aus einer Längenangabe. Beim Laden des Programms reserviert das Betriebssystem dann entsprechend viel Speicher, der dann natürlich keinen bestimmten Inhalt hat. Im BSS-Hunk dürfen folglich ausschließlich BLK.x-Directives stehen, und zwar ohne Angabe eines Füllwertes. Alle Hunks dürfen im Programm nur jeweils genau einmal auftreten. Es ist bei Kick-Ass also nicht möglich, nach Belieben zwischen den Hunks hin und her zu schalten. Mit Ausnahme von CODE, der immer den Anfang des Programms bildet, dürfen die übrigen Hunks in beliebiger Reihenfolge stehen und werden jeweils mit der jeweiligen Directive eingeleitet. Auf Ihrer Kick-Ass-Disk finden Sie ein Beispielprogramm, das alle vier Hunk-Typen verwendet.  (* Ergänzung zum MONITOR-Kapitel, Seite 22 *)  WA Wird tab=0 angegeben oder "auto" im Requester angeklickt, wird in der Datei jeweils ein Tab-Code eingesetzt. WC name name: Dateiname WRITE CODE: Diese Anweisung schreibt den reinen Programm-Code in eine Datei. Entweder muß die Relokationstabelle leer sein (so daß das Programm ohne Adreßkorrektur in jeden Speicherbereich gelegt werden kann), oder Sie müssen zuvor mit der Directive "ORG" einen Speicherbereich festlegen.  (* Ergänzung zum LINKER-Kapitel, Seite 33, letztes Kapitel *)  Ist der Name eines Files "*", so besteht die Datei zuvor aus mehreren Hunks.  (* Neues Kapitel *)  DEBUGGER -------- Wenn Ihr Programm vom Assembler korrekt übersetzt worden ist, heißt das noch lange nicht, daß es auch das tut, was es Ihrer Meinung nach eigentlich sollte. Jeder Programmierer hat wohl schon gemerkt, daß die meiste Arbeitszeit nicht für das Programmieren an sich, sondern für die Fehlersuche benötigt wird. Aber glücklicherweise läßt sich dieser Anteil durch geeignete Hilfen deutlich senken - und in dieser Beziehung hat (seit Version 1.2) Kick-Ass einiges zu bieten. 1. Gewaltsamer Abbruch ---------------------- Zu den ärgerlichsten Erscheinungen des Assembler-Programmierens gehören wohl versehentlich programmierte Endlosschleifen. Der Prozessor hat nun einmal keine Break-Taste wie der BASIC-Interpreter... Kick-Ass aber schon! Immer, wenn Sie aus der Entwicklungsumgebung heraus ein Programm starten, sei es nun mit den Monitorbefehlen "e" bzw. "j" oder mit den entsprechenden Pulldown-Menüs, wird gleichzeitig ein zweiter Task gestartet (was ja auf dem Amiga kein Problem darstellt - ein Grund mehr, sich keinen Atari zu kaufen...). Dieser Task - nennen wir ihn im folgenden "Supervisor-Task" - eröffnet zunächst in der rechten oberen Bildschirmecke ein kleines Fenster mit einem vielversprechenderweise mit STOP beschrifteten Gadget. Anschließend geht der Supervisortask in den Waitingstate, so daß er keine nennenswerte Rechenzeit benötigt. Erst wenn Sie diesen Knopf mit der Maus anklicken, wird dieser Task wieder aktiv und zwingt Ihr Programm, wieder in die Kick-Ass-Umgebung zurückzu- springen. Dazu benutzt er ein sehr brutales Verfahren (daher auch die Überschrift dieses Abschnitts), das auch nicht gerade von gutem Programmier- stil zeugt (aber mir fiel nichts besseres ein): Der Supervisortask sucht den Stack des Haupt-Tasks (kein Problem, denn der steht bekanntlich in der Exec-Task-Struktur), auf welchem zuoberst der Programmzeiger liegt (denn aus der Tatsache, daß der Supervisortask arbeitet, folgt ja, daß der Haupt-Task gerade Frühstück macht - oder was für eine Pause auch immer). Diesen PC verbiegt der Supervisor dann auf eine bestimmte Adresse und wartet ab, bis sein Opfer wieder CPU-Zeit erhält. Das Betriebssystem fällt dann glatt auf diesen simplen Trick 'rein und schickt den Haupt-Task nicht etwa dahin, wo er zuletzt stehengeblieben war, sondern an die erwähnte Adresse. Hier steht Routine, die zunächst einmal den Supervisortask samt seines mickerigen Windows aus dem System schmeißt - nicht etwa aus Rache, sondern weil jener vorerst nicht mehr gebraucht wird. Dann bringt er den eigenen Stackpointer auf einen vernünftigen Wert und springt in den Monitor, nicht ohne zuvor die Registerinhalte auszugeben. Und jetzt das große ABER: Das Betriebssystem mag es manchmal überhaupt nicht, wenn wichtige Routinen unterbrochen werden, schon gar nicht auf diese üble Art und Weise. Aus diesem Grunde überlegt der Supervisor es sich gründlich, bevor er tätig wird, und reißt den Haupt-Task nur dann aus der Programmabarbeitung heraus, wenn dessen PC gerade im eigentlichen Programm steht. Deshalb kann man ein Programm auch nicht aus dem Waiting State erwecken. In Wirklichkeit ist das Stop-Gadget kein einfacher, sondern ein umschalt- barer Knopf. Solange er angewählt ist, prüft der Supervisortask immer wieder, ob der Haupt-Task in einem unterbrechbaren Bereich ist. Wenn Sie es sich anders überlegt haben, können Sie das Stop-Gadget währenddessen durch erneuten Mausklick wieder deaktivieren, worauf sich der Supervisortask wieder schlafen legt. Zuletzt sei noch darauf hingewiesen, daß die Programmunterbrechung natürlich auch nicht funktioniert, wenn Ihr Programm das Taskswitching gesperrt oder den Prozessor in den Supervisor-Modus geschaltet hat. 2. Tracing ---------- Das Abbrechen von amoklaufenden Programmen erspart einem so manches Mal das Rebooten des Systems. Danach kann es an die eigentliche Fehlersuche gehen. Nach der Unterbrechung, wie auch nach einer Exception, werden stets die Registerinhalte ausgegeben. Zunächst ist hier wohl der Inhalt des PCs von Interesse. Wenn Sie diese Adresse beim Moni-Befehl "g#" angeben, sucht Kick-Ass Ihnen automatisch die entsprechende Stelle im Quelltext. Hilft Ihnen das noch nicht weiter, können Sie z.B. an fragwürdigen Stellen den BREAK-Pseudobefehl setzen. Auf diese Weise erfahren Sie beim nächsten Probelauf zumindest, ob der Prozessor überhaupt an diese Stelle kommt, und wenn ja, werden die Registerinhalte an dieser Stelle ausgegeben. Ferner können Sie sich nach dem Break mit "m adr" Variablenwerte ansehen. Oft ist es aber hilfreicher, wenn man dem Prozessor eine Weile "über die Schulter gucken" kann. Dazu dient der Tracer. Der 68000-Prozessor verfügt über einen sog. Trace-Modus. In diesem Modus springt er nach jedem ausgeführten Befehl in eine besondere Exception. Kick-Ass ist in der Lage, - den Prozessor in den Trace-Modus zu schalten, - diese Exception abzufangen, - die Lage auszuwerten und auszugeben - auf Tastendruck wieder mit der Programmabarbeitung fortzufahren. Prinzipiell gibt es zwei Möglichkeiten, in den Trace-Modus zu gelangen: - durch Anwählen des Menüpunkts "Debug/Trace" - oder mit den Directives TRACE und TROFF. Die zweite Art ist vor allem dann sinnvoll, wenn man nur einen bestimmten Teil des Programms "durchtracen" will. Vorher müssen Sie aber noch eine weitere Entscheidung fällen: normal, nur einen Block oder alles tracen. Wenn Sie "trace all" anwählen, wird buchstäblich alles "durchgetracet" - einschließlich den Betriebssystemaufrufen. So etwas ist zwar manchmal ganz interessant, aber bei der Fehlersuche nicht sehr hilfreich, weil ja das Betriebssystem wohl im großen und ganzen ziemlich fehlerfrei sein dürfte (vorsichtig formuliert). Zu allem Überfluß hat das System es auch nicht immer gern, wenn eine eigentlich unteilbare Routine vom Tracer unterbrochen wird. Zum Beispiel führt es todsicher zum Absturz, wenn Sie die OpenWindow-Funktion der Intuition-Library "durchtracen" (Grund: während diese Funktion weitreichend in Intuition eingreift, macht der Tracer Bildschirm- ausgaben -> Kollision kritischer Abschnitte!). In der normalen Betriebsart des Tracers wird daher nur Ihr Programm verfolgt. Wenn der Prozessor von dort z.B. ins Betriebssystem springt, wird der Trace-Modus vorübergehend ausgeschaltet. (Um genau zu sein: es wird nicht etwa der Trace-Modus des Prozessors abgeschaltet, denn wer sollte den nachher wohl wieder einschalten? Vielmehr unterläßt der Tracer jede Bildschirm- ausgabe, solange der Prozessor außerhalb Ihres Programms 'rumwurschtelt. Das hat aber auch zur Folge, daß die Betriebssystemaufrufe deutlich langsamer ablaufen, denn das Tracen frißt immer noch jede Menge CPU-Zeit. Sie können z.B. beobachten, wie ein Window in Zeitlupe geöffnet wird - sehr sehenswert!) Die dritte Betriebsart heißt "Block only". Hier wird nur ein im Editor markierter Block durchgecheckt, während im übrigen Programm (wie oben) das Tracen vertuscht wird. Diese Wahl des zu untersuchenden Bereichs ist übrigens insofern endgültig, als daß später (während des Trace-Vorgangs) kein Umschalten mehr möglich ist. Aber nun zum Tracen selbst: Nach jedem ausgeführten Befehl wird der nächste disassembliert. Im oberen Bereich des Fensters werden die Registerinhalte angezeigt. Dabei werden im Statusregister die einzelnen Bits durch je einen Buchstaben dargestellt ( C=Carry, V=oVerflow...). Ein großer Buchstabe steht für ein gesetztes, ein kleiner für ein gelöschtes Bit. Kick-Ass wartet dann jeweils auf einen Tastendruck, bevor der nächste Befehl ausgeführt wird. Einige Tasten sind aber mit besonderen Funktionen belegt: A (Auto): Ab sofort wartet der Tracer nicht mehr, sondern geht nach der Bildschirmausgabe sofort zum nächsten Befehl über. Beim nächsten Tastendruck kehrt er wieder in den normalen Modus zurück. S (Silent): Die Bildschirmausgabe wird unterdrückt, bis Sie wieder eine Taste drücken. DEL: Falls der Tracer durch eine TRACE-Directive eingeschaltet wurde, wird die entsprechende Directive mit einem NOP-Befehl überschrieben, so daß das Programm an dieser Stelle in Zukunft nicht mehr hängenbleibt. ESC: Programm abbrechen (das STOP-Gadget funktioniert im Tracemodus nicht). Cursor Down: nächsten Befehl überspringen. Natürlich können Sie den Tracer auch mit dem Pull-Down-Menü ausschalten. Zuletzt sei noch darauf hingewiesen, daß der Tracer von Kick-Ass nicht den Exception-Vektor der Task-Struktur, sondern den des Prozessors (Adresse $24) verbiegt. Sollte Ihre Liebe zum Multitasking so weit gehen, daß Sie zwei Programme gleichzeitig verfolgen, dürfte es aus diesem Grund Probleme geben.  *******************************************************************************  Versionsliste:  V 1.10 : erste offizielle Version V 1.12 (05.03.89): Beseitigung einiger Fehler V 1.20 (20.09.89): UPGRADE (Trace-Modus, Bedienung, SEKA-Kompatibilität) V 1.95 (01.12.91): UPGRADE (Bug im Tracemodus beseitigt, Kompatibilität zu ASM-ONE, Turnaroundzeiten verbessert)  *******************************************************************************