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 Registerinhalte können auch geändert werden.
Zum Ändern des Speicherinhalts gibt es den
Speichereditor.
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.
Damit Sie die Speicher- und Registerinhalte ansehen können,
muss die Programmausführung angehalten werden.
Dafür gibt es zwei Möglichkeiten:
-
Sie legen einen oder mehrere Haltepunkte an.
Wenn während der Befehlsabarbeitung ein solcher Haltepunkt
zutrifft, wird angehalten.
-
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 die die Doppelregister zeigen und
unten die nächsten auszuführenden Befehle.
Mit dieser Funktion wird die Programmausführung in normaler
bzw. voller Geschwindigkeit fortgesetzt.
Wenn dabei das Programm auf einen Haltepunkt trifft,
dessen Bedingung erfüllt ist, wird angehalten.
Bei dieser Funktion führt der Debugger das Programm langsam aus.
Sie können so die Abarbeitung des Programms im Debugger verfolgen.
Die Geschwindigkeit der Programmabarbeitung ist in drei Stufen wählbar.
Wenn das Programm auf einen Haltepunkt trifft,
dessen Bedingung erfüllt ist, wird angehalten.
Halte-/Log-Punkt verkörpern eine Bedingung,
bei der die Programmausführung angehalten (Haltepunkt)
und/oder eine Log-Meldung (Log-Punkt) ausgegeben wird.
Es gibt fünf verschiedene Arten von Halte-/Log-Punkten.
Das Anlegen von Halte-/Log-Punkten erfolgt über das Menü
am Fenster oder über das Kontextmenü (rechte Maustaste)
über dem jeweiligen Halte-/Log-Punktbereich.
Das ist die klassische Form eines Halte-/Log-Punktes.
Es wird angehalten bzw. eine Log-Meldung ausgegeben,
wenn die Programmausführung an der angegebenen Adresse
angelangt ist.
Zusätzlich können Sie den Wert eines Registers
prüfen lassen.
Dann wird nur angehalten bzw. eine Log-Meldung ausgegeben,
wenn neben der Adresse auch die Registerwertprüfung erfolgreich war.
Diese läuft folgendermaßen ab:
Vor Abarbeitung des Befehls auf der Halte-/Log-Punktadresse wird der Wert
des ausgewählten Registers mit einer von Ihnen anzugebenden Maske
UND-verknüpft und das Ergebnis dann mit einem ebenfalls von Ihnen
anzugebenden Vergleichswert verglichen.
Dabei ist nicht nur ein Vergleich auf Gleichheit möglich,
sondern auch auf Ungleichheit sowie auf größer als
und kleiner als.
Halte-/Log-Punkte auf Programmadressen können Sie neben den
oben genanten Möglichkeiten auch über das Kontextmenü
der Programmcodeanzeige sowie im Reassembler
über das Kontextmenü anlegen.
Bei diesen beiden Varianten wird gleich die Adresse entsprechend
der Position des Kontextmenüs vorbelegt.
Ein solcher Halte-/Log-Punkt 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 bzw. eine Log-Meldung
ausgegeben werden soll.
Zusätzlich können Sie den Wert der betreffenden Speicherzelle
(Lesezugriff) bzw. den zu schreibenden Wert (Schreibzugriff)
überprüfen lassen.
Auch hier geben Sie Maske, Vergleichsoperator und Vergleichswert an.
Achtung! Der Debugger prüft vor der Ausführung eines
jeden Maschinenbefehls, ob dieser auf den angegebenen Speicherbereich
zugreift.
Aufgrund dieser Arbeitsweise werden jedoch die Speicherzugriffe,
die während einer Interrupt-Annahme getätigt werden
(Lesen der Interrupt-Tabelle im Interrupt-Mode 2 und
Kellern der Rückkehradresse) von keinem Halte-/Log-Punkt erkannt.
Bei diesem Halte-/Log-Punkt geben Sie die Adresse oder
den Adressbereich eines Eingabetors an.
Es wird dann vor einem Eingabebefehl angehalten bzw.
eine Log-Meldung ausgegeben, der von diesem Eingabetor liest.
Die Eingabeadresse kann sowohl mit 8 Bit (2 hexadezimale Ziffern)
als auch mit 16 Bit (4 hexadezimale Ziffern) angegeben werden.
Dementsprechend wird dann auch die Adresse mit 8 oder 16 Bit
geprüft.
Dieser Halte-Log-Punkt ist ähnlich wie einer auf einem Eingabetor,
nur dass er auf Ausgabebefehle reagiert.
Zusätzlich können Sie den auszugebenden Wert
überprüfen lassen.
Bei dieser Form eines Halte-/Log-Punktes 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 bzw. eine Log-Meldung ausgegeben.
Über das Menü Debuggen können Sie beliebig
viele Halte-/Log-Punkte anlegen.
Mit dem Kontextmenü über der jeweiligen Haltepunktliste
ist das auch möglich.
Um einen Halte-/Log-Punkt wieder zu entfernen,
müssen Sie diesen im rechten Bereich des Debugger-Fensters
durch Anklicken markieren.
Sie können auch mehrere Halte-/Log-Punkte markieren.
Anschließend klicken Sie im Menü Debuggen
auf den Eintrag Ausgewählte Halte-/Log-Punkte entfernen.
Optional können Sie auch alle Haltepunkte auf einmal entfernen
(Menüeintrag Alle Halte-/Log-Punkte entfernen).
Halte-/Log-Punkte, die Sie temporär nicht benötigen,
müssen nicht unbedingt entfernt werden.
Sie können diese einfach deaktivieren,
indem Sie die beiden Aktionen (Anhalten und Loggen) deaktivieren.
Bei Bedarf können Sie die gewünschte Akion später
wieder aktivieren.
Der Debugger ist nur solange aktiv, wie das Debugger-Fenster
sichtbar ist.
Wenn Sie Halte-/Log-Punkte angelegt haben und Sie schließen
das Fenster, werden die Halte-/Log-Punkte zwar nicht gelöscht,
jedoch sind sie nicht mehr aktiv.
Der Debugger bietet die Möglichkeit,
Halte-/Log-Punkte aus einer Datei oder aus der Zwischenablage zu
importieren.
Diese Halte-/Log-Punkte 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
Assembler-Option
Im Debugger Halte-/Log-Punkte bzw. Variablen auf Marken anlegen
ein.
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
Einzelschritt über Aufruf hinweg,
Einzelschritt in Aufruf hinein und
Bis RETURN ausführen.
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.
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 gleiche gilt für Blockbefehle und leere DJNZ-Schleifen.
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.
Es werden die Maschinenbefehle bis zum nächsten Return-Befehl
ausgeführt.
Werden dabei Unterprogramme aufgerufen,
so werden diese vollständig ausgeführt.
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.
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 im 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 somit 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.
Ein Programm speichert seine Daten üblicherweise in Variablen.
Da es beim Debuggen sehr hilfreich ist,
die aktuellen Variableninhalte zu sehen und ggf. auch zu ändern,
bietet der JKCEMU Debugger dafür eine Unterstützung.
Allerdings weiß der Debugger nicht, welche Speicherbereiche
für Variablen verwendet werden und welche Datentypen diese haben.
Aus diesem Grund müssen die Variablen dem Debugger erst bekannt
gemacht werden, d.h., sie müssen im Debugger angelegt werden.
Für jede Variable geben Sie eine Adresse, einen Datentyp
und optional einen Namen an.
Wenn Sie das erledigt haben,
zeigt der Debugger die aktuellen Variableninhalte an,
sobald die Programmausführung anhält.
Neben dem manuellen Anlegen können Variablen auch von dem
im JKCEMU integrierten Assembler
importiert werden.
Wenn Sie die Assembler-Option Im Debugger Halte-/Log-Punkte
bzw. Variablen auf Marken anlegen eingeschaltet haben,
wird für jede Marke, die unmittelbar vor einer DS-
oder DEFS-Anweisung steht, eine Variable angelegt.
Im technischen Sinne ist eine Variable im JKCEMU Debugger
nur eine Deklaration, die besagt, wie ein ein oder mehrere Bytes
großer Bereich im Arbeitsspeicher zu betrachten ist,
d.h. ob dort ein numerischer, alphanumerischer oder binärer Wert
gespeichert wird.
Sie können beliebig viele Variablen anlegen.
Den Inhalt des Arbeitsspeichers können Sie sich auch mit dem
Speichereditor anzeigen lassen
und auch ändern.
Das Anlegen von Variablen im Debugger hat jedoch den Vorteil,
dass die Anzeige beim Anhalten der Programmausführung
automatisch aktualisiert wird und dass Sie nur die Bytes sehen,
die Sie interessieren,
auch wenn die Bytes im ganzen Arbeitsspeicher verstreut sind.