Article View: alt.msdos.programmer
Article #343Re: To all who want to program TSR
From: Thorsten Mieze
Date: Sun, 30 Aug 1992 11:24
Date: Sun, 30 Aug 1992 11:24
201 lines
7352 bytes
7352 bytes
Keywords:
In <drice.714963151@ponder> drice@ponder.csci.unt.edu (Keith Rice)
writes :
>In <1992Aug27.153035.15061@tom.rz.uni-passau.de>
>mieze@forwiss.uni-passau.de (Thorsten Mieze) writes:
>>Hi all!
>>During last time, there were often questions about programming TSR
>>in higher languages like C, PASCAL, MODULA etc. in this newsgroup.
>>Notice, that all TSR-programs need an include of assembler, which
>>sets div. parameters (e.g. div. pointers of interrupts) to enable
>>programming the real TSR-program in higher language. The mostly
>Not so. In the book _Turbo Pascal 5.5_ from Borland/Osborne there
>is an example of a screen blanker (I think) TSR written entirely in
>TP 5.5.
That's right. Keith was so kind and sent me the program via email.
Since there are multiple users interested, I'll post it here. Please
understand this as an animation for your own programs, don't use it
commercially. Recognize part II of the article written after the
example-progam.
{$M 2000,0,0}
{$R-,S-,I-,D+,F+,V-,B-,N-,L+ }
Program ScreenSaver;
Uses
DOS, CRT;
Const
TimerInt = $08; (* Timer interrupt *)
KbdInt = $09; (* Keyboard interrupt *)
TimeLimit : Word = 5460; (* Wait 5 minutes before blanking *)
Var
Regs : Registers;
Cnt : Word; (* Counts timer ticks *)
PortNum : Word; (* Port used to disable video *)
PortOff : Word; (* Value to disable video *)
PortOn : Word; (* Value to enable video *)
OldKbdVec : Pointer;
OldTimerVec : Pointer;
i : Real;
Code : Word;
(************************************************************)
Procedure STI;
InLine($FB);
(************************************************************)
Procedure CLI;
InLine($FA)
(************************************************************)
Procedure CallOldInt(Sub:Pointer);
Begin
InLine($9C/ { PUSHF }
$FF/$5E/$06); { CALL DWORD PTR [BP+6] }
End;
(************************************************************)
Procedure Keyboard(Flags,CS,IP,AX,BX,CX,DX,
SI,DI,DS,ES,BP : Word); Interrupt;
Begin
CallOldInt(OldKbdVec); (* Call original interrupt *)
If (Cnt >= TimeLimit) Then (* Restore screen, if disabled *)
Port[PortNum] := PortOn;
Cnt := 0; (* Reset counter *)
STI;
End;
(************************************************************)
Procedure Clock(Flags,CS,IP,AX,BX,CX,DX,
SI,DI,DS,ES,BP : Word); Interrupt;
Begin
CallOldInt(OldTimerVec); (* Call original interrupt *)
If (Cnt > TimeLimit) Then (* If timer limit is reached, *)
Port[PortNum] := PortOff (* disable video *)
Else
Inc(Cnt,1);
STI;
End;
(************************************************************)
Begin
(* If user entered a number parameter, *)
(* compute the delay factor. *)
If ParamCount = 1 Then
Begin
Val(ParamStr(1),i,code);
If (Code = 0) and (i > 0) and (i < 11) Then
TimeLimit := Trunc(i*18.2*60);
End;
Regs.AH := $0F; (* Determine the type of video *)
Intr($10,Regs); (* adapter in use (Mono or CGA) *)
If Regs.AL = 7 Then (* Mono adapter *)
Begin
PortNum := $3B8;
PortOff := $21;
PortOn := $29;
End
Else
Begin
PortNum := $3D8;
PortOff := $25;
PortOn := $2D;
End;
(* Save original interrupts *)
GetIntVec(KbdInt, OldKbdVec);
GetIntVec(TimerInt, OldTimerVec);
(* Install new interrupts *)
SetIntVec(TimerInt, @Clock);
SetIntVec(KbdInt, @Keyboard);
Cnt := 0; (* Initialize counter *)
Keep(0); (* Terminate and stay resident *)
End.
--------------------------------------------
So far, so good.This program includes little inlines, but we won't
call them assemlerROUTINES... (not a flame) %)
Just one thing : This is a screen-saver, working absolutely
correct. But this programm doesn't contain any DOS-commands/-inter-
rupts in its TSR part (Procedure CallOldInt, Procedure Keyboard and
Procedure Clock).
If you want to program TSR underlaying this example-program, be sure,
that you NEVER execute any DOS-interrupt or DOS-interrupt using com-
mand. A short example : It's easy, to execute the Interrupt 21h, func-
tion 30h, which will return the actual DOS-version...one of many ways
to execute a DOS-interrupt. Application :
[...]
var regs2 : registers;
[...]
regs2.ah := $30;
intr ($21,regs2);
[...]
Your stupid AT would starve in 99% at each execution. %(
Motivation : the non-reentrance of DOS (that means, DOS can't store
all relevant registers more than one time and will over-
write these relevant informations, whenever an DOS-inter-
rupt is executed, which interrupts the first access of
DOS). (hope it's clear %) )
=> Problem : How can I execute DOS-interrupts, since I need to use
them.
Solution :
Whenever DOS executes a DOS-function (e.g. interrupt) it sets a flag
called INDOS and resets it, when ready. The TSR routine which will use
DOS-routines, should read this flag, before going on. The INDOS flag
is installed to a fix place in the memory, and it's adress can be re-
ceived by excuting the DOS-interrupt 21h function 34h. If one sets a
pointer to this adress when installing the TSR routines, he can always
see, a DOS-routine is in execution, or not (flag >0 => DOS-routine
execution).
But unfortunately this isn't the whole solution. It'll be all fantas-
tic during another program is active, and not the DOS-Shell. The
INDOS-flag is reset mostly.
If there's no program running, the DOS-shell is active. But whenever
the DOS-shell is active, the INDOS-flag is set nearly the whole time,
since DOS is waiting for input in a DOS-loop. The TSR-program can't
run. But there's a way : while DOS is waiting for input, it uses the
interrupt 28h for activating bgrd-processes (such as printer-spooling)
each waiting-loop. At this time, it stores no relevant registers and
one can interrupt, although INDOS is set. If one writes his own 28h
routine, in which it executes the original one, the TSR can be exe-
cuted afterwards.
Now theres just one more problem : Whenever timecritical actions are
in execution, TSR may not interrupt. Timecritical actions are in gen-
eral access-routines to FD and HD. These routines use the interrupt 13h
during execution, so that one can write it's own 13h routine the same
way, one did with the 28h routine, and disable (flag) TSR execution
during 13h is active.
Now, the TSR should run without danger.
Thorsten Mieze
(* Katzen wuerden Whiskey saufen %) *)
Technical Details
Message-ID:
<1992Aug30.112458.19365@tom.rz.uni-passau.de>Path:
arc1-ca.pugleaf.net!sparky!uunet!news.univie.ac.at!tuvie!Sirius.dfn.de!math.fu-berlin.de!informatik.tu-muenchen.de!rz.uni-passau.de!forwiss.uni-passau.de!miezeShow Full Headers
Complete Article Headers
Newsgroups: alt.msdos.programmer Path: arc1-ca.pugleaf.net!sparky!uunet!news.univie.ac.at!tuvie!Sirius.dfn.de!math.fu-berlin.de!informatik.tu-muenchen.de!rz.uni-passau.de!forwiss.uni-passau.de!mieze From: mieze@forwiss.uni-passau.de (Thorsten Mieze) Subject: Re: To all who want to program TSR Message-ID: <1992Aug30.112458.19365@tom.rz.uni-passau.de> Sender: news@tom.rz.uni-passau.de (News-Operator) Nntp-Posting-Host: elendil.forwiss.uni-passau.de Organization: University of Passau, Germany Date: Sun, 30 Aug 1992 11:24:58 GMT Lines: 201