home *** CD-ROM | disk | FTP | other *** search
- {---------------------------------------------------------------}
- { TESTMD.PAS ]
- { }
- { Demoprogramm zur Nutzung von MDEBUG in eigenen Turbo Pascal- }
- { Programmen (Turbo Pascal Version 4.0 oder höher) }
- { }
- { Achtung: }
- { Zur Ermittlung des Userints sollte nur CHECKMD verwendet }
- { werden (keine Konstante einsetzen!), da Turbo Pascal einen }
- { Interrupt zwischen 60h und 66h (normalerweise den Interrupt }
- { 60h) in der Entwicklungsumgebung für eigene Zwecke gebraucht! }
- { (Getestet in Version 5.0) }
- { }
- { (c) by Bernd Schemmer 1989, 1990, 1991, 1992 }
- { }
- { Benötigt die Object-Dateien CALLMD.OBJ, CHECKMD.OBJ, }
- { MDCMD.OBJ und KONVERT.OBJ zur Compilierung }
- { }
- { letzter Update: 09.05.1992, Bernd Schemmer }
-
- USES dos,crt;
-
- {---------------------------------------------------------------}
- { Aufbau des Status-Records von MDEBUG }
-
- TYPE
- StatusTable = RECORD
- PSP : WORD; { Code-Segment von MDEBUG }
- Int08 : POINTER; { Adresse der alten Routine }
- { für den Int 8h }
- Int09 : POINTER; { -"- Int 9h }
- Int16 : POINTER; { Adresse der von MDEBUG }
- { benutzten Int 16h-Routine }
- Version : STRING; { Versionskennung von MDEBUG}
- { als Pascal-String }
- END;
-
- VAR
- StatusPtr : ^StatusTable;
-
- {---------------------------------------------------------------}
- { Aufbau des Hilfsregister-Arrays von MDEBUG }
- { (9 Register von R0 bis R8 mit Wort-Größe) }
-
- TYPE
- HilfsRegisterSet = ARRAY[0..8] of WORD;
-
- VAR
- HilfsRegisterPtr : ^HilfsRegisterSet;
-
- {---------------------------------------------------------------}
- { Hilfsvariablen }
-
- VAR
- regs : REGISTERS; { Register-Record zum Aufruf von }
- { MDEBUG }
- userint : BYTE; { Nummer des Userints }
-
- VAR
- TestString : STRING[$3F];
- Erklaerung : STRING[$3F];
- passwort : STRING[4]; { Variable zum Speichern des }
- { Passwortes }
-
- CONST
- _Erklaerung = '**** Der Inhalt der Variablen TESTSTRING kann geändert werden ***';
-
- CONST
- CR_LF = #13#10;
- BELL = #7;
-
- CONST
- mdmessages : ARRAY[0..3] of STRING =
- ('im Monitor',
- 'im Interpreter',
- 'in der Onlinehilfe des Monitors',
- 'in der Onlinehilfe des Interpreters');
-
- {---------------------------------------------------------------}
- { Einbinden der Routine zum Testen, ob MDEBUG geladen ist }
- {$L CheckMd}
-
- {---------------------------------------------------------------}
- { CheckMD }
- { }
- { Funktion: Ermittelt ob MDEBUG geladen ist und ob ein }
- { Userint installiert ist }
- { }
- { Eingabe: - }
- { }
- { Ausgabe: }
- { Funktionswert: -1 : MDEBUG nicht installiert }
- { 0 : MDEBUG ohne Userint installiert }
- { 60h - 67h : MDEBUG installiert und der Funktions- }
- { wert ist die Nummer des Userints }
- { Andere Werte sollten nicht vorkommen }
- { }
- { Besonderheiten: Benutzt die MCBs }
- {---------------------------------------------------------------}
-
- { Deklaration der Funktion (FAR!): }
-
- {$F+} FUNCTION CheckMD:BYTE; EXTERNAL; {$F-}
-
- {---------------------------------------------------------------}
- { Einbinden der Routine zum Aufruf von MDEBUG }
- { (Der Aufruf kann auch über die Funktion INTR() erfolgen) }
- {$L callmd}
-
- {---------------------------------------------------------------}
- { CallMD }
- { }
- { Funktion: Aufruf des Userints von MDEBUG }
- { }
- { Eingabe: intnumber : Nummer des Userints von MDEBUG }
- { (Ermittelt über CheckMD !) }
- { regs : Registerwerte für den Aufruf }
- { }
- { Ausgabe: regs : evtl. geänderte Registerwerte }
- {---------------------------------------------------------------}
-
- { Deklaration der Prozedur (FAR!): }
-
- {$F+}
- PROCEDURE CallMd( intnumber : BYTE;
- VAR regs : REGISTERS); EXTERNAL;
- {$F-}
-
- {---------------------------------------------------------------}
- { Einbinden der Routine zur Ausführung von Befehlen über MDEBUG }
- {$L MDCMD}
-
- {---------------------------------------------------------------}
- { MDCMD }
- { }
- { Funktion: Ausführen von Befehlen über MDEBUG }
- { }
- { Eingabe: CheckInts : TRUE : Unterdrückt die Interrupts 20h, }
- { 27h und die Funktionen 0h und }
- { 31h des Interrupts 21h }
- { während der Ausführung der }
- { Befehl(e) }
- { FALSE: keine Überprüfung der Interrupts}
- { commands : Befehl(e) für MDEBUG als Pascal-String }
- { regs : Registerwerte für den Aufruf }
- { }
- { Ausgabe: regs : evtl. geänderte Registerwerte }
- { }
- { Bes.: Benötigt die Routine CHECKMD, setzt temporär die }
- { Interrupts 20h, 21h und 27h um. }
- { Besondere Zeichen im String für die Befehle: }
- { ^ ->> falls das folgende Zeichen im Intervall }
- { zwischen 'A' und 'Z' liegt, wird der Wert }
- { der entsprechenden Taste mit CTRL übergeben.}
- { (Ansonsten wird es so übergeben) }
- { z.B. '^M' entspricht der Taste <RETURN> }
- { '^m' wird nicht konvertiert! }
- { # ->> falls dem Zeichen '#' mindestens eine Ziffer}
- { folgt, wird/werden diese als SCAN-Code einer}
- { Taste interpretiert und übergeben (Ansonsten}
- { wird das Zeichen so übergeben) }
- { z.B. }
- { '#4400' ist der SCAN-Code der Taste <F10> }
- { '#0DM' wird übergeben als <RETURN> gefolgt }
- { von der Taste 'M' }
- { '#W' wird so übergeben! }
- {---------------------------------------------------------------}
-
- { Deklaration der Prozedur (FAR!): }
-
- {$F+}
- FUNCTION MDCMD( CheckInts: BOOLEAN;
- VAR regs : REGISTERS;
- VAR commands : STRING):BYTE; EXTERNAL;
-
- {$F-}
-
- {---------------------------------------------------------------}
- { Hilfs-Routinen }
-
- {---------------------------------------------------------------}
- { Einbinden der externen Assembler-Routinen zum Erstellen von }
- { Hexstrings }
-
- {$L konvert.obj}
-
- {$F+ ebenfalls als FAR! }
- {---------------------------------------------------------------}
- { HexByte }
- { }
- { Funktion: Umwandeln eines Bytes in einen 2-stelligen }
- { Hexstring }
- { }
- { Eingabe: zahl - Umzuwandelndes Byte }
- { }
- { Ausgabe: Als Funktions-Wert wird der Hexstring zurückgegeben}
- {---------------------------------------------------------------}
-
- FUNCTION HexByte(zahl : BYTE):STRING; EXTERNAL;
-
- {---------------------------------------------------------------}
- { HexWord }
- { }
- { Funktion: Umwandeln eines Wortes in einen 4-stelligen }
- { Hexstring }
- { }
- { Eingabe: zahl - Umzuwandelndes Wort }
- { }
- { Ausgabe: Als Funktions-Wert wird der Hexstring zurückgegeben}
- {---------------------------------------------------------------}
-
- FUNCTION Hexword(zahl : WORD):STRING; EXTERNAL;
-
- {$F-}
-
- {---------------------------------------------------------------}
- { LeseTaste }
- { }
- { Funktion: Ausgabe einer Wartemeldung und lesen einer Taste }
- {---------------------------------------------------------------}
-
- PROCEDURE LeseTaste;
-
- VAR
- c : CHAR;
-
- BEGIN
- WHILE keypressed DO c:=ReadKey;
- write(CR_LF,'Bitte eine Taste drücken [ESC für Programm-Ende] ...');
- c:=ReadKey;
- writeln(CR_LF);
- IF c=CHAR($1B) THEN
- BEGIN
- writeln;
- writeln('Programm durch Benutzer abgebrochen!');
- writeln;
- halt(255);
- END;
- END;
-
- {---------------------------------------------------------------}
- { Prozeduren zur Demonstration der Nutzung von MDEBUG }
-
- {---------------------------------------------------------------}
- { CheckMDEBUGError }
- { }
- { Funktion: Testen, ob der Aufruf von MDEBUG erfolgreich war }
- { }
- { Eingabe: RetCode = von MDEBUG gelieferter RETURN-Code }
- { }
- { Bes.: Falls ein Fehler auftrat, wird das Programm nach }
- { der Ausgabe einer Fehler-Meldung beendet }
- {---------------------------------------------------------------}
-
- PROCEDURE CheckMDEBUGError(RetCode:WORD);
-
- BEGIN
- IF (RetCode AND $FF00) = $FF00 THEN
- BEGIN
- writeln;
- writeln(BELL,'*** Fehler beim Aufruf von MDEBUG aufgetreten! ***');
- writeln;
- END;
- IF RetCode=$FFFF THEN
- BEGIN
- writeln('Fehler: Aufruf von MDEBUG ist nicht erlaubt!');
- writeln(' Zur Behebung des Fehlers sollten Sie MDEBUG mit ');
- writeln(' dem Parameter ''SET'' einmal aufrufen!');
- writeln(CR_LF);
- halt(255);
- END
- ELSE
- IF RetCode=$FFFE THEN
- BEGIN
- writeln('Fehler: Falsches Passwort eingegeben!');
- writeln(CR_LF);
- halt(255);
- END
- ELSE
- IF RetCode=$FFFD THEN
- BEGIN
- writeln('Fehler: Falscher Bildschirm-Modus!');
- writeln(' MDEBUG kann, falls kein Bildschirmtreiber geladen ist,');
- writeln(' nur in einem Textmodus mit mindestens 80 Zeichen pro');
- writeln(' Zeile und mindestens 25 Zeilen pro Seite aufgerufen');
- writeln(' werden!');
- writeln(CR_LF);
- halt(255);
- END
- ELSE
- IF RetCode=$FFFC THEN
- BEGIN
- writeln('Fehler: Falsche Funktionsnummer für den User-Int verwendet!');
- writeln(CR_LF);
- halt(255);
- END
- END;
-
- {---------------------------------------------------------------}
- { GetMDEBUGPasswort }
- { }
- { Funktion: Aufruf von MDEBUG zur Ermittlung, ob ein Passwort }
- { aktiv ist }
- {---------------------------------------------------------------}
-
- PROCEDURE GetMDEBUGPasswort;
-
- VAR
- k : BYTE;
-
- BEGIN
- writeln('--> Aufruf von MDEBUG zur Ermittlung, ob ein Passwort aktiv ist');
- writeln(' (Funktion 06h des Userints)');
- writeln;
- regs.ax:=$0600; { keine Abfrage des Passwortes }
- CallMD(Userint,regs);
-
- IF regs.al <> $0 THEN
- BEGIN
- writeln(' Passwort von MDEBUG ist aktiv, für die folgenden Aufrufe kann');
- writeln(' das Passwort eingegeben werden. Falls kein Passwort eingegeben');
- writeln(' wird, muß bei jedem Aufruf das Passwort neu eingegeben werden.');
- writeln;
- write (' Passwort (<RETURN> -> kein Passwort): ');
-
- k:=textattr;
- textattr:=0; { Passwort unsichtbar eingeben! }
- readln(Passwort);
- textattr:=k;
- IF passwort='' THEN
- passwort:=#0;
- END
- ELSE
- writeln('--> Passwort von MDEBUG nicht aktiv oder nicht installiert.');
- writeln;
- Lesetaste;
- writeln;
- END;
-
- {---------------------------------------------------------------}
- { ShowRegs }
- { }
- { Funktion: Ausgabe der Inhalte der Register }
- { }
- { Eingabe: which : Auszugebender Record }
- {---------------------------------------------------------------}
-
- PROCEDURE ShowRegs(which:REGISTERS);
-
- BEGIN
- WITH which DO
- BEGIN
- writeln(' AX = $',hexword(ax),
- ' BX = $',hexword(bx),
- ' CX = $',hexword(cx),
- ' DX = $',hexword(dx));
- writeln(' SI = $',hexword(si),
- ' DI = $',hexword(di),
- ' BP = $',hexword(bp),
- ' DS = $',hexword(ds),
- ' ES = $',hexword(es));
- END;
- END;
-
- {---------------------------------------------------------------}
- { Normaler Aufruf von MDEBUG }
-
- PROCEDURE CallMDEBUG;
-
- BEGIN
- writeln('--> Aufruf von MDEBUG ohne Änderung der Registerwerte: ');
- writeln(' (Funktion 04h des Userints)');
- writeln;
- regs.ax:=$0400;
-
-
- regs.ds:=seg(passwort);
- regs.si:=ofs(passwort)+1; { DS:SI zeigt auf das Passwort }
-
- writeln(' Register vor dem Aufruf: ');
- ShowRegs(regs);
-
- LeseTaste;
-
- CallMD(Userint,regs);
- CheckMDEBUGError(regs.AX);
-
- writeln(' Register nach dem Aufruf: ');
- ShowRegs(regs);
-
- END;
-
- {---------------------------------------------------------------}
- { Normaler Aufruf von MDEBUG }
-
- PROCEDURE CallMDEBUG1;
-
- BEGIN
- writeln('--> Aufruf von MDEBUG zur Anzeige einer Variablen (hier eines Strings): ');
- writeln(' (Funktion 03h des Userints)');
- writeln(' Bitte einen String eingeben: ');
- write (' ');
- readln(teststring);
- writeln;
- regs.ax:=$0300;
-
- regs.es:=Seg(TestString);
- regs.di:=ofs(TestSTring); { ES:DI zeigt auf die Variable }
-
- regs.ds:=seg(passwort);
- regs.si:=ofs(passwort)+1; { DS:SI zeigt auf das Passwort }
-
- writeln;
- writeln(' Register vor dem Aufruf: ');
- ShowRegs(regs);
-
- LeseTaste;
-
- CallMD(Userint,regs);
- CheckMDEBUGError(regs.AX);
-
- writeln(' Register nach dem Aufruf: ');
- ShowRegs(regs);
-
- writeln;
- writeln(' Inhalt des TestStrings nach dem Aufruf: ');
- writeln(' ',Teststring);
- END;
-
- {---------------------------------------------------------------}
- { Normaler Aufruf von MDEBUG }
-
- PROCEDURE CallMDEBUG2;
-
- VAR
- temp : BYTE;
- okay : BOOLEAN;
-
- BEGIN
-
- REPEAT
- writeln('--> Aufruf von MDEBUG zur Ausführung von Befehlen: ');
- writeln(' (Die Interrupts 20h und 27h und die Funktionen 0h und 31h des');
- writeln(' Interrupts 21h können NICHT ausgeführt werden!)');
-
- regs.ds:=seg(passwort);
- regs.si:=ofs(passwort)+1; { DS:SI zeigt auf das Passwort }
-
- regs.ax:=$0700;
- CallMD(Userint,regs);
- CheckMDEBUGError(regs.ax);
-
- IF regs.al <= 3 THEN
- BEGIN
- highvideo;
- writeln(' ***** MDEBUG startet ', mdmessages[regs.al]);
- normvideo;
- END;
- writeln(' Bitte die Tasten bzw. die Befehlszeile eingeben (* <RETURN> für Ende): ');
- write (' ');
- readln(teststring);
- okay:= (teststring = '*');
- writeln;
-
- IF NOT OKAY THEN
- BEGIN
- regs.ds:=seg(passwort);
- regs.si:=ofs(passwort)+1; { DS:SI zeigt auf das Passwort }
-
- writeln;
- writeln(' Register vor dem Aufruf: ');
- ShowRegs(regs);
-
- LeseTaste;
-
- temp := MDCmd(TRUE,regs,teststring);
- { Falls die Interrupts 20h, 27h }
- { und die Funktionen 0 und 31h }
- { des Interrupts 21h ausgeführt }
- { werden sollen, muß als erster }
- { Parameter FALSE eingegeben }
- { werden! }
- CheckMDEBUGError(Regs.AX);
-
- writeln(' Register nach dem Aufruf: ');
- ShowRegs(regs);
-
- writeln;
- END
-
- UNTIL okay
- END;
-
- {---------------------------------------------------------------}
- { Ermitteln des Status von MDEBUG }
-
- PROCEDURE GetMDEBUGStatus;
-
- BEGIN
-
- regs.ds:=seg(passwort);
- regs.si:=ofs(passwort)+1; { DS:SI zeigt auf das Passwort }
-
- regs.ah:=$0;
- CallMD(Userint,regs);
- CheckMDEBUGError(regs.AX);
- StatusPtr:=ptr(regs.ds,regs.si);
- writeln('--> Status von MDEBUG : ');
- writeln(' (Funktion 0h des Userints)');
- writeln(' Adresse der Statustabelle: $',hexword(regs.ds),':$',hexword(regs.si));
- writeln;
- WITH StatusPtr^ DO
- BEGIN
- writeln(' PSP von MDEBUG : $',hexword(psp));
- writeln(' alter Int08 : $',hexword(seg(int08^)),':$',HexWord(ofs(int08^)));
- writeln(' alter Int09 : $',hexword(seg(int09^)),':$',hexword(ofs(int09^)));
- writeln(' Int16 von MDEBUG : $',hexword(seg(int16^)),':$',Hexword(ofs(int16^)));
- writeln(' Version: : ',version);
- END;
- WITH regs DO
- BEGIN
- writeln(' Monitor-Adresse : $',hexword(es),':$',hexword(di));
- writeln(' Monitor-Farbe : $',hexbyte(ch));
- writeln(' Monitor-Startzeile : $',hexbyte(bh));
- writeln(' Interpreter-Farbe : $',hexbyte(cl));
- writeln(' Interpreter-Startzeile : $',hexbyte(bl));
- writeln(' Basis-Prozess-Nummer : $',hexbyte(dh));
- writeln(' Scan-Code des Hotkeys : $',hexbyte(ah));
- writeln(' ASCII-Code des Hotkeys : ','''',CHAR(al),'''');
- writeln;
-
- write(' Aufruf über den Hotkey: ');
- IF (dl AND $04) <> 0 THEN write('<CTRL>-');
- IF (dl AND $08) <> 0 THEN write('<ALT>-');
- IF (dl AND $02) <> 0 THEN write('<LeftSHFIT>-');
- IF (dl AND $01) <> 0 THEN write('<RightShift>-');
- writeln('<',char(al),'>');
- writeln;
- END;
-
- writeln;
- LeseTaste;
- END;
-
- {---------------------------------------------------------------}
- { Ermitteln der Adresse der HilfsRegister von MDEBUG }
-
- PROCEDURE GetMDEBUGRegAdress;
-
- VAR
- k : BYTE;
-
- BEGIN
- writeln('--> Adressen und Inhalt der HilfsRegister: ');
- writeln(' (Funktion 01h des Userints)');
- writeln;
- regs.ah:=$01;
-
- regs.ds:=seg(passwort);
- regs.si:=ofs(passwort)+1; { DS:SI zeigt auf das Passwort }
-
- CallMD(Userint,regs);
- CheckMDEBUGError(Regs.AX);
- { ES:DI zeigt auf R1 }
- { ->> Array beginnt bei ES:DI-2 }
- HilfsRegisterPtr:=ptr(regs.es,regs.di-2);
- FOR k:=0 TO 8 DO
- BEGIN
- writeln(' Register R',k,' bei $',hexword(regs.es),':$',hexword(regs.di),' -> $',
- hexword(HilfsRegisterPtr^[k]));
- regs.di:=regs.di+2;
- END;
- writeln;
- lesetaste;
- END;
-
- {---------------------------------------------------------------}
- { Macro zur Ermittlung der Flags }
- { }
- { Funktionswert: Inhalt des Flag-Registers }
- {---------------------------------------------------------------}
-
- FUNCTION GetFlags:WORD;
- INLINE($9C/ { PUSHF }
- $58); { POP AX }
-
- {---------------------------------------------------------------}
- { Hauptprogramm }
- {---------------------------------------------------------------}
-
- BEGIN
- clrscr;
- Erklaerung:=_Erklaerung;
- passwort:='????';
- passwort:='';
-
- regs.ax:=0; { Registerwerte vorbesetzen }
- regs.bx:=0;
- regs.cx:=0;
- regs.dx:=0;
- regs.ds:=DSeg;
- regs.es:=Dseg;
- regs.si:=0;
- regs.di:=0;
- regs.flags:=GetFlags; { Wichtig! }
-
- writeln;
- writeln(' ********************************');
- writeln(' *** Demo-Programm für MDEBUG ***');
- writeln(' ********************************');
- writeln;
- Userint:=CheckMD;
- IF (Userint = 0) OR (Userint = $FF) THEN
- BEGIN
- writeln('Fehler: MDEBUG nicht geladen, oder kein Userint installiert');
- halt(255);
- END
- ELSE
- BEGIN
- writeln('-> MDEBUG geladen, der Userint ist der Interrupt Nr. ',
- Userint,' (Hexadezimal: $',hexbyte(userint),')');
- writeln;
- writeln('-> Aufrufe von MDEBUG über den Userint');
- writeln;
-
- GetMDEBUGPasswort;
- writeln;
- GetMDEBUGStatus;
- writeln;
- GetMDEBUGRegAdress;
- writeln;
- callMDEBUG;
- writeln;
- callMDEBUG1;
- writeln;
- callMDEBUG2;
- writeln;
- writeln('***** Demo beendet. *****');
- END;
- END.
-
- {---------------------------------------------------------------}
-
-