home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* PTR.PAS *)
- (* eigener Druckertreiber mit Turbo-Pascal *)
- (* System: MSDOS 3.1 & Turbo Pascal 3.0 *)
-
- PROGRAM NewPtr;
-
- CONST userint = $63; { neuer Interrupt }
- deviceint = $17; { alter Gerätevector (z.B. Printer,}
- { Screen,RS232) in diesem Fall }
- { $17 = Printer }
- segbuf = $80; { Speicher f. Register. }
- { CS ist Bezugssegment }
- { +0 = Dseg +2 = Sseg }
- { +4 Sseg des Treibers }
- { +6 = Eseg des Rufers }
- { +8 = AX Kommandocode }
- {+10 = DX Druckernummer }
-
- VAR Segment,Offset : INTEGER;
-
- (*$I REGS8088.INC *)
- (*$I MAKEINT.INC*)
-
- {==========================================================}
- { diese Procedure kann ohne Restriktionen vom Anwender }
- { programmiert werden wobei IN: AX,DX }
- { OUT: AX }
- { ANMERKUNG: bei anderen Geräten (Screen,RS232) andere }
- { Schnittstelle zum BIOS, d.h keine generelle Lsg. }
- { abhängig wie Register benutzt werden }
-
- PROCEDURE Interpret;
-
- VAR AH,AL: BYTE;
- AX,DX: INTEGER;
- r: Regs8088_;
-
- PROCEDURE PrintChar(ch:CHAR);
- { druckt Zeichen über eigentliche BIOS-Routine aus }
- VAR v: Regs8088_;
- BEGIN
- v.DX:=DX; { DX global in InterPret }
- v.AX:=00+Ord(ch); { Code AH = 0 => Drucken }
- Intr(userint,v);
- MemW[Cseg:segbuf+8]:=v.AX { setze etwaigen Status }
- { für Rückgabe }
- END; { PrintChar }
-
- BEGIN
- AX:=MemW[Cseg:segbuf+8]; DX:=MemW[Cseg:segbuf+10];
- AL:=Lo(AX); AH:=Hi(AX);
- IF AH=0 THEN BEGIN { AH=0 Code für Drucken }
-
- {""""""""""""""""""" Anwenderteil "" Beispiel """""""""""""}
- { hier kann entsprechend auf ein eingegangenes Zeichen }
- { reagiert werden. Da globale Variablen erhalten bleiben, }
- { können auch Algorithmen mit Gedächtnis geschrieben wer- }
- { den. z.B. können Codesequenzen dadurch erkannt und inter-}
- { pretiert werden. }
- { ANMERKUNG: Das komplette Turbo-Laufzeitsystem kann }
- { benutzt werden !!!! }
-
- CASE Chr(AL) OF { Bsp: Umsetzen der Umlaute }
- 'ä': PrintChar('a');
- 'ö': PrintChar('o');
- 'ü': PrintChar('u');
- 'Ä': PrintChar('A');
- 'Ö': PrintChar('O');
- 'Ü': PrintChar('U');
- 'ß': BEGIN PrintChar('s'); PrintChar('s') END
- ELSE PrintChar(Chr(AL)) { normales Zeichen ! }
- END;
- IF Chr(AL) IN ['ä','Ä','ö','Ö','ü','Ü'] THEN
- PrintChar('e');
- END
- ELSE BEGIN
- r.AX:=AX; { Kommando }
- r.DX:=DX; { Druckernummer ! }
- Intr(userint,r); { führe alten Interrupt }
- MemW[Cseg:segbuf+8]:=r.AX
- END
- END; { Interpret }
-
- {----------------------------------------------------------}
- { auf diese Procedure wird der Interrupt-Vector gerichtet. }
- { Es darf keine Variable angelegt werden, da sonst anderer }
- { Code erzeugt wird, und der Versatz +7 nicht mehr stimmt. }
- { (siehe Activate) }
- PROCEDURE NewInterrupt;
-
- BEGIN
- INLINE($53/$51/$52/ { PUSH BX-DX }
- $57/$56/$55/$1e/$06/ { PUSH DI,SI,BP,DS,ES }
- { rette alle Register außer AX,SS,SP }
- { (benutze alten SP weiter) }
- $2e/$a3/segbuf+8/$00/ { MOV CS:[segbuf+8],AX }
- $2e/$89/$16/segbuf+10/$00/
- { MOV CS:[segbuf+10],DX }
- { rette AX und DX in Speicherbereich die von }
- { Interpret verarbeitet werden wobei AH=Kom-
- { mandobyte, AL=Druckbyte, DX=Druckernummer }
- $8c/$d0/ { MOV AX,SS }
- $2e/$a3/segbuf+6/$00/ { MOV CS:[segbuf+6],AX }
- { rette altes Stacksegment. WESENTLICH ! Da
- { Pascal intensivst über Stack arbeitet(Dynamik)}
- { muß eigener Stack verwendet werden. }
- $2e/$a1/segbuf+0/$00/ { MOV AX,CS:[segbuf] }
- $8e/$d8/ { MOV DS,AX }
- $2e/$a1/segbuf+2/$00/ { MOV AX,CS:[segbuf+2] }
- $8e/$d0/ { MOV SS,AX }
- $2e/$a1/segbuf+4/$00/ { MOV AX,CS:[segbuf+4] }
- $8e/$c0); { MOV ES,AX }
- { Lade DS,ES,SS mit den Werten die bei der In- }
- { stallation gesichert wurden. Jede Turbo Pascal}
- { Procedure ist nun voll lauffähig. }
-
- Interpret; { eigentliche Service-Routine aufrufen}
-
- INLINE($2e/$a1/segbuf+6/$00/ { MOV AX,CS:[segbuf+6] }
- $8e/$d0/ { MOV SS,AX }
- { Stelle nun SS wieder auf Rufer ein (SP wurde }
- { durch Turbo Pascal benutzt, aber muß natürlich}
- { unverändert von Interpret zurückkommen, darum }
- { braucht er nicht gesichert zu werden). }
- $07/$1f/$5d/$5e/$5f/ { POP ES,DS,BP,SI,DI }
- $5a/$59/$5b/ { POP DX-BX }
- { hole alle Registerwerte vom Stack }
- $2e/$a1/segbuf+8/$00/ { MOV AX,CS:[segbuf+8] }
- { Da AX Rückgabeparameter ist (Status- }
- { information) muß AX beladen werden. }
- $cf) { IRET }
- END; { NewInterrupt }
-
- {==========================================================}
-
- BEGIN
- WriteLn;
- WriteLn('modifizierter BIOS-Interrupt:');
- IntGet(userint,Segment,Offset);
- IF Segment<>0 THEN
- WriteLn('Interrupt schon benutzt, Treiber nicht ',
- 'aktiviert...')
- ELSE BEGIN
- IntGet(deviceint,Segment,Offset);
- { bestimme Adresse des Original-Vectors }
- IntSet(userint,Segment,Offset);
- { und kopiere sie in unseren Vektor }
- IntSet(deviceint,Cseg,ofs(NewInterrupt)+7);
- (* unseren Treiber in Interrupt einhängen *)
- MemW[Cseg:segbuf ]:=Dseg; { rette die Segmentregi- }
- MemW[Cseg:segbuf+2]:=Sseg; { ster DS/SS/ES um vom }
- { BIOS aus zu arbeiten. }
- INLINE($2e/$8c/$06/segbuf+4/0); { MOV CS:[segbuf+4],ES }
- WriteLn('Treiber aktiviert... ');
- MakeResident;
- END;
- END.