Übersicht:
Autor des Programms ist Tony Cheal, welcher mir Ende 1997 die Weitergabe seines Programms auf diesem Wege ausdrücklich gestattet hat. Wer also selber daraus keine Rechtsansprüche erhebt noch dies zu tun beabsichtigt, kann dieses unübertroffene Monitorprogramm kostenlos verwenden und von hier erhalten. - Zur Qualität dieses Monitors nur, daß es mir nach vielen Versuchen mit der Talent Workbench, dem (grauenhaften) QMON und anderen ähnlichen Teilen erst damit überhaupt möglich wurde, meine sämtlichen hier vorgestellten Programme bei zumutbarem Aufwand hinreichend zu prüfen und sicherzumachen.
Das Programm in seiner derzeitigen Gestalt ist "freeware", d.h. es kann beliebig verwandt werden, sofern es nicht verändert, gewerbsmäßig weitergegeben oder eine fremde Urheberschaft (auch auf Teile daraus) behauptet wird.
Der Programmcode wurde an ein paar Stellen korrigiert, wo es Kollisionen
mit den jüngeren Betriebssystemen gab, rsp. mit dem JM-System. Vor allem
aber ist er für den universellen Einsatz, d.h. ohne besondere
Konfiguration, auch mit der QXL und anderen QDOS-artigen Systemen
einschließlich SMSQ mit Processoren ab 68010
entsprechend überarbeitet.
Der "C1MON" wurde (und wird) erfolgreich mit allen QL-Roms (auch in GC) ab JM
benutzt, sowie in der Super-GC (mit JS oder Minerva und 68020) und mit der QXL
(68EC040) mit SMSQ seit Version 2.16 - der erbärmliche Zustand welcher
Software im übrigen Auslöser dieser Variante für die betr.
Processoren war - aktuell SMSQ 2.76 und SMSQ/E 2.85; außerdem im
Atari-Mega-ST mit E.32-Software und mit SMSQ/E 2.79, sowie in UQLX-Emulator
(Linux).
Einzige Stelle, an der es (noch) hakt, ist bei 32-bit-adressierten relativen Sprüngen, wo im "trace"-Modus der mitlaufende Disassembler einen Sprung auf die nächste ungerade Adresse liest und dadurch, obwohl der Code selbst richtig abgearbeitet würde, einen "illegal"-Abbruch erzwingt. Vorläufig läßt sich Abhilfe u.a. dadurch schaffen, daß man mit "go" und einen danach gesetzten "break point" (s.u.) den Sprung über solche Stellen hinweg veranlaßt.
Geändert u.a.:
job-header wurden unter gewissen Bedingungen von den clone-Jobs rsp. beim
trace überschrieben, oder beim Anlegen von clones und bei der
Übergabe an den trace-Hilfsjob nicht richtig übernommen.
job-referenz bei clone-Zeilen ergänzt, sodaß wahlweise immer die augenblick-
liche oder nur die beim Einrichten des clone gültige Referenz
benutzt wird. Mangels Erweiterungsmöglichkeit wird hierzu das
parameterlose clone-Kommando benutzt, das den Original-Jobnamen
(nicht den u.u. mit HOTKEY-Zuweisung gegebenen) verändert und
den geltenden Zustand durch z.B. QJ oder JOBS erkennbar macht.
der Name "C1M" erscheint bei automatisch mit dem überwachten
Job wechselnder Referenz, "C1Mon" beim Ursprungszustand, wo die
Referenz stets dieselbe bleibt.
pointer-i.f. durch Schutzfenster keine Probleme mehr damit,
pick außerdem automatisches PICKen des Monitorbildes beim Auflaufen
auf einen der Ausnahmevectoren:
trace, illeg, level 7, chk, priv., trap5..15
poke alle Schreiboperationen in den Speicher finden im supervisor-
Modus statt, sodaß zum einen die Daten in jedem System wirklich
auch ankommen, und zum andern dadurch bei manchen Gerätetypen
nicht irgendwelche blödsinnigen bus-errors ausgelöst werden.
Ausnahme sind u.u. die als "Programm-Referenz" für den betr.
Processor spezifizierten Adressenbereiche oder im Atari "nicht
vorhandene" Adressenbereiche.
rom-prüfung permanent durch zusätzlichen Hilfsjob zur Kontrolle auf
Codeveränderungen im Rom-Bereich, wird nur bei Systemen aktiv,
deren "ROM" im RAM liegt (GC, QXL etc). Bremst das System
um ca 3%, kann aber, wenn das stört oder die Überwachung
entbehrlich geworden ist, ohne weiteres mit z.b. QR "rc" ent-
fernt werden. Der überwachende Hilfsjob legt eine crc-Tabelle
für 48 1K-Blöcke an, die nach jeder Änderung im Code neu
ermittelt wird (um Dauersignal zu vermeiden). Wurde durch
Vergleich mit der vorher gewonnenen Prüfzahl eine Veränderung
festgestellt, erscheint in Fenster #4 des C1Mon die Nummer des
betr. Blocks (ab null), und es ertönt ein Signal. beides jedoch
um bis zu 8 sec. gegenüber der Auslösung verzögert. Die
Reaktionszeit kann durch Erhöhen der Priorität des "rc"-Jobs
minimal halbiert werden, was aber zulasten der Systemgeschwin-
digkeit geht (verringerung um weitere ca. 10%).
Verfahrensbedingt kann es beim "trace" über eine Subroutine oder
Trap hinweg gelegentlich zu paarweisen Veränderungsmeldungen kommen.
trace (u.a. Ausnahmevectoren)
Stackbearbeitung Processor-unabhängig eingerichtet.
HINWEIS: Durch das Bearbeitungsverfahren bedingt wirken
breapoints nicht, wenn sie auf einen TAS-code gerichtet
sind. Man setzt sie dann besser auf den nächsten Befehl.
trap-redirection
eigene Trap-Umleitung überwachter Jobs wird berück-
sichtigt (führte vorher u.u. zum Systemzusammenbruch).
Start:
EX C1M;"{Parameter-String}"
Die Parameter-Übergabe wird als Tastatureingabe in Fenster #1 des
Monitors ausgewertet.
Ende:
no br:j 0:quit <enter>als Tastatureingabe im Monitor. Von außen her mit "QR", "RJOB" etc. Dabei bleibt dann aber der vom Monitor (notwendigerweise) mit Besitzer 0 eingerichtete namenlose trace-Hilfsjob wirkungslos bestehen, er muß - und kann gefahrlos - ggf. gesondert entfernt werden.
Übersicht:
Kommando Verwendung
adressierung gilt nach Schreibweise für effektive Adressen
eines Assemblers entsprechend der lea-Anweisung:
123456 als absolute Adresse sedezimal
&123456 dto dezimal
%11111111 binaer
alle Zahlenwerte < 2^16 werden auf bp bezogen
xxxx£ "£" angehängt für kleinere absolute Adressen.
10(a3,d4.w) ausgewertet als 10 + a3 + d4.w (vorzeichenerweitert)
aber auch
10(58(a6),a6,d0)
etc.
du (a7) liefert also den Stack-Dump (s.u.)
bp Basispointer, der Anfang des aktuellen jobs (s.u.),
bp ist wie ein Register auch einstellbar.
#kanalnummer kann jedem Befehl, der eine Ausgabe bewirkt,
nachgestellt werden, und lenkt sie in den betr.
Kanal um - bei trace wirkungslos.
Taste/Befehl Wirkung
<blank> generell Trennzeichen zwischen Parametern
cursor down mit altem Befehl weitermachen
cursor up dto., pc zurückzählen
bei trace nur weiterdisassemblieren;
. Register oder Label (neu) setzen, etwa
.d1 1234 setzt d1 auf $00001234
aber
.bp 1234 setzt den Basispointer, werte unter 2^16
werden auf den aktuellen Jobanfang bezogen,
für wirkliche Adressen fügt man ein '£' an.
.d0 0+"A" setzt d0 auf $00000041
.d0 "A" $41000000
.d0 10<8 $00001000
ass Assembler aktivieren
br Breakpoints anzeigen
br adr Breakpoint setzen - wird nach dem nächsten T(race)
aktiv. Wirkt als Monitor sowohl im Hintergrund als
auch nach aktivieren eines Jobs. Selbst das PIF kann
hieran nichts verderben!
Unwirksam im Bereich (wirklich) im ROM befindlicher
Adressen, Abhilfe z.b. durch: watch_l PC <adresse>.
c #kanalnummer c1-kanal schließen
ch kanäle des aktuellen jobs anzeigen
clon alle eingabe-clones anzeigen
clon {eingabezeile} die befehle dieser zeile werden je von einem
unabhängigen eigenen job periodisch ausgeführt.
d disassembler fortsetzen (beginnt bei bp)
d 120(a6,a4.w) disassemblieren ab effektiver adresse 120(a6,a4.w)
du dump, entsprechend.
e {rechenausdruck} Resultat eines Ausdrucks hinschreiben;
(effektive) Adressen werden durch vorangestelltes
"@" (at) zum Ausdruck in Sinne dieses Kommandos.
end Assembler verlassen
flags;{flagsymbole} stellt die Arbeitsweise ein, {Flagsymbole}
u.a. An Dn Rn (A-/D-/R-Register) sowie
jsr trap etc, wie bei "help" angezeigt.
g Aufruf, nach T ggf bis zum nächsten breakpoint.
Datenüberwachung (s.u., "w") erfasst nicht die in
den Subroutinen entstehenden Werte. trace wird
solange suspendiert, kann durch Cursor hoch oder
runter reaktiviert werden.
h kurze Liste der Befehle und Flags
hea heap-Blöcke des aktuellen Jobs anzeigen
j alle Jobs anzeigen
der aktuelle Job ist durch Bezug der Basisadresse
auf bp gekennzeichnet
i #kanal farbe INK einstellen
j job-id macht den angegebenen zum aktuellen Job
k job-id Job entfernen
l filename File als Job laden, starten mit t, g o.dgl.
m 0 oder 1 Bildschirm(re)initialisierung
no b adr den breakpoint bei {adr} löschen
no b alle breakpoints löschen
no w entsprechend für "watchpoints"
o #nn name einen Kanal einrichten
o#1,{filename} führt die Kommandodatei {filename} wie eine
Tastatureingabe aus (#1 ist der i/o-Kanal)
pa paper, wie ink
peek wie SBasic, <blank> oder ',' als Trennzeichen
poke dto.
pr job-id wert setzt Job-Priorität, ohne {id} für aktuellen Job
q <ea> bei <ea> beginnende link-Liste anzeigen
quit C1Mon aufgeben
r Registeranzeige aktualisieren
t Trace fortsetzen (beginnt bei pc)
t <ea> dto. mit Startadresse
w watchpoints anzeigen
w <ea> val watchpoint setzen, zur Wirkung s. breakpoints,
erfaßt blind durchlaufene Subroutinen nicht.
windows nach Auswahl mit Cursortasten neue Grenzen einrichten
abwechselnd werden Vorgabe oder aktuelle Grenzen
angeboten
window #nn das Fenster #nn justieren.
Kommando-modifizierende Flags Zweck Ur-Zustand
rel Anzeige rel(bp) ein
pc rel(pc) ein
job rel(job) aus
hex aktuelle Zahlenbasis ein
asc DUMP auch in ASCII ein
an Adress-Register-Anzeige ein
dn Daten- " " ein
rn Hilfs- " " aus
dis Trace mit Disassembly ein
regs Registeranzeige nach
Trace-, Job-, Load-Ausführung ein
trap Trace auch Trapausführung aus
jsr Trace durch Subroutinen ein
break breakpoints aktivieren ein
watch watchpoints aktivieren ein
no nächstgenannte flag-Aktion stillegen
Die Flags können jedem Kommando nach einem unmittelbar an jenes anschließenden Semikolon mitgegeben werden, oder mit Hilfe des Pseudo-Befehls "flags;". Sie bleiben unabhängig von anderen Kommandos bis zur nächsten Änderung wirksam.
Kommandos:
Die Bezeichnungen müssen nur soweit hingeschrieben werden, wie zur
eindeutigen Unterscheidung erforderlich.
<cursor runter> Wiederholung des vorigen Kommandos
<cursor hoch> dto., Trace ohne Codeausführung
.<adresse> dasselbe wie poke (s.dort) mit .L-Vorgabe,
.d0 Register D0.L besetzen, etc.
border [#chan] [<colour>]
border-Breite 1 liegt fest
break [<adr>]
breakpoints anzeigen, rsp. bei <adr> neu setzen
channels
Kanäle des aktuellen Jobs anzeigen
clone [<kommando>]{:<kommandos>}
alle clone-Jobs anzeigen,
rsp eine beliebige Eingabezeile unabhängig zur
selbstätigen und kontinuierlich wiederholten
Ausführung als Job einrichten, z.B.
clone du#4 (a6,a3) <enter>
gibt laufend aktualisiert den Speicherinhalt ab der durch
(A6,A3.L) adressierten Stelle im C1M-Fenster #4 aus.
Zusätzliche Funktion für clone ohne Parameter (neu):
Umschaltung der dump-Anzeige von clone-Zeilen
für Bezug auf aktuellen Job oder den Job, der
beim Einrichten der clone-Zeile aktuell war.
close [#chan]
zuletzt benutzten rsp. angegebenen Kanal schließen
cls [#chan]
compare [#chan[,]] <adr bereich> <adr> [[;]flags]
dis [#chan[,]] [<adr>][,<zeilen>] [[;]flags]
dump [#chan[,]] [<adr>][,<zeilen>] [[;]flags]
eval [<wert>[[\]zahlenbasis]]
find_[<size>] [#chan[,]] <adr bereich> <wert> [[;]flags]
flags {[no]<flag>}*
<flag(s)> als neue Vorgabe einstellen
go [<adr>]
heap <adr> <wert>
<wert> Bytes Speicher reservieren und bei
<adr> dessen Anfangsadresse ablegen
help
Kommandoliste anzeigen
ink [#chan] [<colour>]
job <job-id>
Job in die Überwachung holen, <job-id> wird aktueller Job.
jobs [#chan]
alle Jobs anzeigen
kill <job-id>
load <device&filename> [<adr>]
nobreak [<adr>]
breakpoints löschen, alle rsp. nur den bei <adr>
noheap <adr>
Heap-Bereich ab in <adr> abgelegter Adresse freigeben
nowatch_[<size>] <adr bereich> <wert>
alle rsp. angegebenen watchpoint löschen
nowatches
alle watchpoints löschen
open #chan <device>
mode [<mode>]
move <adr bereich> <adr>
paper [#chan] [<colour>]
poke_[<size>] <adr bereich> [<wert>]
Vorgabe ist Byte-Format
priority [<wert> [<job-id>]]
queue [#chan[,]] [<adr>[,<zeilen>]]
quit
regs [#chan[,]] [[;]flags]
release [<job-id>]
save device&filename <adr bereich> [<dataspace>]
Sichert aktuellen Job ganz und mit Dataspace = 256 Bytes:
save flp1_jobfile_exe = 100
strip [#chan] [<colour>]
suspend [<job-id>]
trace [#chan[,]] [<adr>][,<zeilen>] [[;]flags]
watch_[<size>] <adr bereich> <wert>
watchpoint setzen
watches
watchpoints anzeigen
window [#chan]
mit den Cursortasten kann das (angegebene) Fenster
justiert werden, ALT.. verändert die Maße.
windows
alle fenster der reihe nach neu einstellen
Parameter:
Notation
..}* beliebig viele Wiederholungen zulässig
| Alternative
[...] optionale Angabe
ein einzelner Punkt dient als Leeroperation zur Beseitigung
von Mehrdeutigkeiten, etwa
poke_w 5 -3
würde zwei Bytes an der Speicherstelle 2(BP) löschen,
poke_w 5 .-3
trägt dagegen an Adresse 5(BP) die Zahl 3 ein.
Zusammenfassung
<wert> = [$]<hex-zahl> | &<dezimalzahl>
| ^<oktalzahl> | %<binärzahl>
| "<string>" | '<string'
| <wert> | ~<wert>
Verknüpfung zweier <wert>e mit
+ - * / Grundrechenarten
^ Divisionsrest, MOD
~ bitweise Ergänzung zu 1, NOT
! & bitweise OR, bitweise AND
< > links rsp rechts schieben
Sonderfunktionen
<basis>%<wert> <wert> zur Zahlen<basis> angegeben
?<adresse> <wert> an der Stelle <adresse>
@<adresse> Typenanpassung adresse -> wert
zum Rechnen beispielsweise mit
einer "effektiven Adresse":
eval @30
eval @25(a6,d0.w)
[ ] Klammerung von Auswertungsoperationen
<adresse> = <wert> {<wert>(bp) wenn <wert> < $10000}
| <wert>£ {erzwungen absolut zählende Adresse}
| <register>
| [<wert>](<adresse>{,<adresse>[.w|.l]}*)
(<adresse>) liefert den Inhalt der Speicherstelle <adresse>;
<wert>(<adresse>) etc. entspricht der üblichen Assemblernotation,
kann aber beliebig erweitert benutzt werden, und
sowohl mit <register>n als auch mit <wert>en:
$c0(a0,d1.w,a6,10(a6))
<register> = d0...d7 | a0...a7 | r0...r7 | bp | tp | pc | sr
(der supervisor-sp A7' ist nicht adressierbar!)
<bereich> = <adresse1>[,<adresse2>]
| <adresse>\<wert>
| = Bereich des aktuellen Jobs
<adr bereich> = <adresse> einfache Adresse
| <adresse1>,<adresse2> Anfang und Ende-1
| = ganzer aktueller Job-Bereich
| <adresse>\<wert> Kommando mit <adresse> in
Anzahl <wert> Wiederholungen
<size> = b | w | l
<channel> | <lines> = <dezimalzahl>
<mode> | <colour> | <job-id> | <channel-id> | <base> = <wert>
Fehlermeldungen, "Exception"-Anzeige:
1. Ergänzungen (.hpr):
Ausnahmevectoren, soweit sie z.B. durch mt.trapv des QDOS
besetzt wurden, werden nach Möglichkeit ohne Halt ausgeführt.
Um den Ablauf sicherzustellen, muß auch beim Programmstart
im Job 0 der Job durch Kommando explizite angegeben und bei
anderen Jobs vor deren Aufgabe ein auch danach noch existierender
Job festgelegt werden.
Die Ausnahmebehandlung stellt sich selbstätig auf den jeweils
zugrundeliegenden Processor ein; C1M spielt dadurch auch in
Systemen ab 68010 - geprüft mit 68020 (SGC) und 68040 (QXL).
Weitere Änderungen erlauben den Betrieb in allen Varianten
des Schwarzen QL ab JM-ROM.
2. Fehleranzeige, z.B.:
Illegal Instruction
JB=<job-id> PC=<adresse> SR=<status>
oder
Address Trap Error
FC=nnn XY @<adresse> IR=<instruction code>
darin bedeuten
FC = 001 user-Datenzugriff
010 " Programm "
101 supervisor-Datenzugriff
110 " Programm "
111 Interrupt-Quittung
X = I Procesor-Anweisung ausführend
E Exception "
Y = R Unterbrechung im Lese-Zyklus
W " Schreib "