Link to home
Start Free TrialLog in
Avatar of ravipal
ravipal

asked on

Invoking a TSR

Can anybody give me a sample TSR code just to print "Hello World" when ALT+SHIFT is pressed.
I am using MS C 7.00
Avatar of ravipal
ravipal

ASKER

Adjusted points to 30
Screen output is very difficult in TSRs becasue DOS is not reentrant.   Neither is the BIOS or at least some parts of it.

If you're working with DOS, you can easily output text into a text mode screen by writing character into the memory.  The idea is very simple.  The 1st char of the 1st line is the address 0xb800:0000 in color mode and 0xb000:0000 in monochrome mode.  The next byte following is the attribute (color, blink, underline, etc), the next byte is the char of in the second position on the line, etc...
ASKER CERTIFIED SOLUTION
Avatar of vladimir_12345
vladimir_12345

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
This is a vey dangerous example... depend to implementation of the Run-Time Library.... printf may use function 21 of DOS... and this will cause problems with nonreenterability of DOS functions...I solved it many years ago using "busy" flag and keyboard iddle function originally implemented by MS for background PRINTing :) (i used Turbo Pascal 5.5 that time)
I'll send the source of it tommorow :)
If it is necesary to call printf in a 21interrupt the dos critical data should be saved.
However in a TSR it is preferable to directly write to screen as shchuka has said.
Do not call a printf() in any TSR because almost all implementations of printf() uses DOS fn 48 to malloc and DOS is not reentrant. You must directly write to video memory at B800:0000.
Also the code to remove the TSR will cause problems. The best methode is to find the start of MCB (Memory Control Block) chain and follow it to find the memory blocks owned by the TSR and release them one by one (Highly Complex!).
 
Hi...
Here is example of the legitimate TSR...
Sorry but I don't have any time to translate it to C...
and I don't have any sutable compiler to debug it now...
but it's very easy to translate

Note:
  The IntKbd procedure doesn't perform real operations...
it's just triggering an flag that should be processed in appropriate time.
  The IntTime and IntKvantDos procedures are responsible for the processing
initiation.
  The IntTime checks the "DOS Busy" flag, and the IntKvatDos checks the
state when DOS waits for input...
  It is undefined what procedure is going to be executed first...
so you have to implement both of them

      Good Luck...
P.S. Change to something better than DOS :) (UNIX or NT or Win95 at least)
      

{$A+,B-,D-,E-,F-,I-,L-,N-,O-,R-,S-,V-}
{$M 1024,0,0}
Uses
  Dos;

Const
  FileName : string = 'DIALOG.DAT';
  Message  : string = 'Yes';

Var
  KbdIntVec      : procedure;
  IntKvantDosVec : procedure;
  IntTimeVec     : procedure;
  f              : Text;
  Flag           : boolean;
  DosWork        : ^byte;
  Reg            : registers;

{$F+}

Procedure FileWrite;

begin
  Rewrite(f);
  Write(f,Message);
  Close(f);
  Flag:=false
end;

Procedure IntTime; interrupt;

begin
  inline($FA);
  if Flag and (DosWork^=0) then FileWrite;
  inline($FB);
  inline($9C);
  IntTimeVec
end;

Procedure IntKvantDos; interrupt;

begin
  inline($FA);
  if Flag then FileWrite;
  inline($FB);
  inline($9C);
  IntKvantDosVec
end;

Procedure IntKbd; interrupt;

begin
  Flag:=(Port[$60]=$44);
  inline($9C);
  KbdIntVec
end;

{$F-}
begin
  Assign(f,FileName);

  inline($FA); { CLI }

  Reg.Ah:=$34; { Set DosWork to Flag of Dos activity }
  Intr($21,Reg);
  DosWork:=Ptr(Reg.Es,Reg.Bx);

  GetIntVec($28,@IntKvantDosVec);
  SetIntVec($28,@IntKvantDos);

  GetIntVec($8,@IntTimeVec);
  SetIntVec($8,@IntTime);

  GetIntVec($9,@KbdIntVec);
  SetIntVec($9,@IntKbd);

  inline($FB);

  Keep(0)
end.