Ü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 "