Debugger

Der Debugger dient dazu, die Programmausführung an beliebiger Stelle anzuhalten, einzelne Befehle im Schrittbetrieb abzuarbeiten und so das Geschehen im Emulator zu überwachen. Dabei ist es auch möglich, die Speicher- und Registerinhalte anzusehen. Die Registerihalte können auch geändert werden. Zum Ändern des Speicherinhalts gibt es den Speichereditor.

1. Debugger starten

Sie befinden sich im Hauptfenster und klicken im Menü Extra, Untermenü Werkzeuge, den Punkt Debugger... an. Die weitere Beschreibung bezieht sich auf das Debugger-Fenster.

2. Programmausführung anhalten

Damit Sie die Speicher- und Registerinhalte ansehen können, muss die Programmausführung angehalten werden. Dafür gibt es zwei Möglichkeiten:
  1. Sie legen einen oder mehrere Haltepunkte an. Wenn während der Befehlsabarbeitung ein solcher Haltepunkt zutrifft, der zudem auch aktiviert sein muss, wird angehalten.
  2. Sie klicken im Menü Debuggen auf den Punkt Programmausführung anhalten.
Jedesmal wenn die Programmausführung anhält, wird der Inhalt des Debugger-Fensters aktualisiert, d.h., Sie sehen im linken Bereich des Fensters die Registerinhalte, in der Mitte die ersten Bytes der Speicherbereiche, auf denen die Doppelregister zeigen und unten die nächsten auszuführenden Befehle.

3. Haltepunkte

Es gibt vier verschiedene Arten von Haltepunkten, die bei unterschiedlichen Bedingungen zum Anhalten der Programmausführung führen.

3.1. Haltepunkt auf Adresse

Das ist die klassische Form eines Haltepunktes. Es wird angehalten, wenn die Programmausführung auf die angegebene Adresse stößt.

3.2. Haltepunkt auf Speicher

Ein solcher Haltepunkt reagiert auf Zugriffe auf eine Speicherzelle bzw. auf einen Speicherbereich. Sie können angeben, ob nur bei Lese-, nur bei Schreib- oder bei Lese- und Schreibzugriffe angehalten werden soll.

Zusätzlich können ein Wert und eine Maske angeben werden. Dann wird nur angehalten, wenn der angegebene Wert mit dem gelesenen bzw. zu schreibenden übereinstimmt. Dabei werden nur die Bits verglichen, die in der Maske gesetzt sind.

3.3. Haltepunkt auf E/A-Tor

So ein Haltepunkt ist ähnlich wie einer auf den Speicher. Anstelle einer Speicherzelle oder eines Speicherbereichs wird eine Ein-/Ausgabeadresse oder eine Gruppe von zusammenliegenden IO-Ports überwacht.

Die E/A-Haltepunktadresse können Sie als 8 Bit- (2 hexadezimale Ziffern) oder 16 Bit-Wert (4 hexadezimale Ziffern) angeben. Der emulierte Mikroprozessor unterstützt offiziell nur E/A-Adressen mit 8 Bit. Allerdings sind aufrund seines undokumentierten Verhaltens auch 16-Bit-E/A-Adressen möglich. Ob Sie nun die E/A-Haltepunktadresse mit 8 oder 16 Bit angeben (müssen), hängt davon ab, ob das emulierte System mit 8 oder 16-Bit-IO-Ports arbeitet.

Auch bei Haltepunkte auf E/A-Tore können ein Wert und eine Maske als zusätzliches Kriterium angegeben werden. Allerdings zeigt das nur bei Ausgabebefehlen eine Wirkung.

Bei Eingabebefehlen wird ein Wert als zusätzliches Kriterium deshalb nicht unterstützt, weil immer vor Ausführung des betreffenden Befehls angehalten wird und der Emulator nicht in jedem Fall wissen kann, welcher Wert dann bei der eigentlichen Befehlsausführung gelesen werden würde.

3.4. Haltepunkt auf Interrupt-Quelle

Bei dieser Form eines Haltepunktes geben Sie eine im emulierten System vorhandene Interrupt-Quelle (z.B. PIO oder CTC) an. Es wird dann angehalten, sobald die Interrupt-Quelle einen Interrupt auslöst und dieser vom Mikroprozessor auch angenommen wird, d.h., es wird vor dem ersten Befehl der Interrupt-Service-Routine angehalten.

3.5. Verwaltung der Haltepunkte

Über das Menü Debuggen können Sie beliebig viele Haltepunkte anlegen. Mit dem Kontextmenü über der jeweiligen Haltepunktliste ist das auch möglich.

Um einen Haltepunkt wieder zu entfernen, müssen Sie diesen im rechten Bereich des Debugger-Fensters durch Anklicken markieren. Anschließend klicken Sie im Menü Debuggen auf den Eintrag Haltepunkt entfernen.

Optional können Sie auch alle Haltepunkte auf einmal entfernen (Menüeintrag Alle Haltepunkte entfernen).

Haltepunkte, die Sie temporär nicht benötigen, müssen Sie nicht unbedingt entfernen. Sie können diese Haltepunkte auch einfach deaktivieren und später bei Bedarf wieder aktivieren.

Der Debugger ist nur solange aktiv, wie das Debugger-Fenster sichtbar ist. Wenn Sie Haltepunkte angelegt haben und Sie schließen das Fenster, werden die Haltepunkte zwar nicht gelöscht, jedoch wird dann dort auch nicht mehr angehalten.

3.6. Haltepunkte importieren

Der Debugger bietet die Möglichkeit, Haltepunkte aus einer Datei oder aus der Zwischenablage zu importieren. Diese Haltepunkte können dabei auch einen Namen haben. So ist z.B. der Import der Markentabelle eines Assemblers möglich, um für jede Marke einen Haltepunkt anzulegen.

Die Markentabelle des JKCEMU-Assemblers können Sie sogar automatisch in den Debugger importieren lassen. Schalten Sie dazu die entsprechende Assembler-Option ein.

4. Schrittbetrieb

Mit Schrittbetrieb ist gemeint, dass nach dem Anhalten der Programmausführung einzelne Befehle oder Befehlsgruppen abgearbeitet werden und danach automatisch wieder die Programmausführung angehalten wird.

Die Funktionalitäten des Schrittbetriebs finden Sie im Menü Debuggen unter den Punkten Über Aufruf springen, In Aufruf springen und Aus Aufruf herausspringen.

Den Schrittbetrieb beenden Sie ganz einfach durch Fortsetzung der Programmausführung. Klicken Sie dazu im Menü Debuggen den Punkt Bis Haltepunkt ausführen an.

Wenn Sie sich im Schrittbetrieb befinden und Sie schließen des Debugger-Fenster, geht der Emulator in den Pause-Zustand über. Sie können dann im Hauptfenster im Menü Extra auf Fortsetzen klicken, oder Sie öffnen wieder den Debugger.

4.1. Über Aufruf springen

Es wird ein einzelner Maschinenbefehl abgearbeitet. Handelt es sich jedoch um den Aufruf eines Unterprogramms, so wird das ganze Unterprogramm ausgeführt und erst danach wieder angehalten. Das Ende eines Unterprogramms wird dabei anhand des Stack Pointers erkannt. Sobald dieser wieder den gleichen Wert wie vor dem Unterprogrammaufruf hat, wird angehalten.

Blockbefehle und leere DJNZ-Schleifen werden ebenfalls übersprungen, d.h. sie werden bis zum Ende abgearbeitet. Bei der Funktion Über Aufruf springen wird nämlich die Programmausführung niemals angehalten, wenn der Befehlszeiger (Program Counter) nach Abarbeitung eines Maschinenbefehls immer noch auf den gleichen Befehl zeigt.

4.2. In Aufruf springen

Es wird immer nur ein einzelner Maschinenbefehl abgearbeitet. Handelt es sich um den Aufruf eines Unterprogramms, so wird nur der CALL-Befehl abgearbeitet und somit vor dem ersten Maschinenbefehl des Unterprogramms wieder angehalten.

Bei Blockbefehlen wird nur ein Zyklus des Blockbefehls abgearbeitet und danach wieder angehalten.

4.3. Aus Aufruf herausspringen

Es werden die Maschinenbefehle bis zum nächsten Return-Befehl ausgeführt. Werden dabei Unterprogramme aufgerufen, so werden diese vollständig ausgeführt.

4.4. Registerinhalte und Flags ändern

Im Schrittbetrieb, d.h. wenn die Programmausführung angehalten wurde, können die Inhalte der Register geändert werden. Geben Sie dazu den gewünschten neuen Wert in das jeweilige Feld hexadezimal ein. Die Werte der einzelnen Flags können Sie festlegen, indem Sie auf die entsprechenden Boxen im oberen Bereich des Fensters klicken und so ein Häkchen setzen oder entfernen.

5. Befehle aufzeichnen

Eine weitere Möglichkeit der Verfolgung des Geschehens im Emulator ist die Befehlsaufzeichnung. Dabei werden vor der Abarbeitung eines jeden Maschinenbefehls die Adresse, die Inhalte der wichtigsten Register und der anstehende Maschinenbefehl in Form einer Zeile in eine Textdatei geschrieben. Diese können Sie sich dann mit einem Editor ansehen, z.B. mit dem in JKCEMU eingebauten Texteditor.

Die Befehlsaufzeichnung schalten Sie über den Schalter Befehle aufzeichnen im Menü Debuggen ein und wieder aus. Immer wenn Sie die Befehlsaufzeichnung einschalten, werden Sie nach dem Namen der Datei gefragt, in der die Befehle aufgezeichnet werden sollen.

Achtung! Die Befehlsaufzeichnung schreibt pro Maschinenbefehl eine ganze Zeile in eine Textdatei. Diese Textdatei wächst deshalb sehr schnell und sehr stark an. Sie sollten deshalb die Befehlsaufzeichnung nicht zu lange eingeschaltet lassen und sicherstellen, dass auf dem Speichermedium ausreichend Platz ist. Außerdem wird die Programmausführung in Abhängigkeit von der Schreibgeschwindigkeit des Speichermediums deutlich gebremst.