home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / MADTRB38.ZIP / INTR.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1986-02-08  |  7.6 KB  |  188 lines

  1. {$V-}  { These compiler directives should not be changed }
  2. {$K-}
  3. {$C-}
  4. {$R-}
  5.  
  6. program Demonstrate_Interrupt_Handlers;
  7.  
  8. { This program is placed in the public domain by Steve Wood, author of
  9.   the book Using Turbo Pascal, published by Osborne McGraw-Hill. The
  10.   techniques used are based on those presented by Jim Camelford in the
  11.   T.U.G. Lines. This example has been modified to be activated directly
  12.   by the calling program rather than by the timer interrupt or the
  13.   keyboard interrupt. The advantage of this approach is that you can
  14.   be certain that the interrupt does not occur during DOS/Turbo I/O
  15.   processing. This means that your interrupt handler may use Turbo's
  16.   I/O without fear of problems caused by the fact that neither Turbo nor
  17.   DOS is re-entrant.
  18.  
  19.   Compile as a .COM program with segment sizes specified as follows:
  20.   For cOde enter  3B      The cOde & Data values were determined by
  21.   For Data enter   4      compiling the program.
  22.   For mAx  enter 400      mAx is important because it limits the heap
  23.   For mIn  enter 400      so that all of memory is not allocated. The
  24.                 ----     value selected must be large enough to satisfy
  25.   cOde+Data+mAx  73B      the heap/stack requirements of the program.
  26.                           When you enter the cOde and Data values note
  27.                           the modified values that Turbo displays in the
  28.                           option list. The sum of those two values plus
  29.                           the value entered for mAx is the amount of memory
  30.                           that must be allocated for this program. See
  31.                           mem_size in the const section below.}
  32.  
  33. const ZERO        = $00;
  34.       INTR_VECTOR = $80; { Defines the interrupt vector for the
  35.                            interrupt routine being defined.
  36.                            Be sure it does not conflict with
  37.                            other interrupt handlers that have
  38.                            been or will be installed. }
  39.  
  40.  
  41.  
  42. { Typed constants hold values pertinent to the calling
  43.   program (hold_xxx) and the interrupt program (new_xxx). }
  44.  
  45.       hold_sseg   : Integer = ZERO;
  46.       hold_sp     : Integer = ZERO;
  47.       new_dseg    : Integer = ZERO;
  48.       new_sseg    : Integer = ZERO;
  49.       new_sp      : Integer = ZERO;
  50.       mem_size    : Integer = $073B;  { Indicates the amount of memory
  51.                                         ( in 16 byte paragraphs )
  52.                                         to be reserved for the resident
  53.                                         interrupt handler. This should be
  54.                                         equal to or greater than the sum
  55.                                         of the code segment size, data
  56.                                         segment size and heap/stack size,
  57.                                         all of which must be specified
  58.                                         when the program is compiled. }
  59.  
  60.  
  61. type RegPack  = record
  62.                   case Boolean of
  63.                     TRUE  : (ax,bx,cx,dx,bp,si,di,ds,es,flags : Integer);
  64.                     FALSE : (al,ah,bl,bh,cl,ch,dl,dh          : Byte);
  65.                 end;
  66.  
  67.  
  68. var   regs    : RegPack;
  69.  
  70.  
  71.   procedure Demo_Intr; { This is the procedure that is activated by
  72.                          interrupt $80. }
  73.  
  74.     const ARROW    = #205#205#16#32; {Displays as a right arrow.}
  75.  
  76.     var   hold_vid : array[1..2000] of Integer;
  77.           hold_x,
  78.           hold_y   : Integer;
  79.           inchr    : Char;
  80.  
  81.  
  82.     function  Mono_Monitor: Boolean;
  83.         var  video_type : Byte;
  84.  
  85.       begin
  86.         video_type := (Mem[$0000:$0410] and $30);
  87.         case video_type of
  88.           $20 : Mono_Monitor := FALSE;
  89.           $30 : Mono_Monitor := TRUE;
  90.           else  begin
  91.                   WriteLn(#7); Halt; { Somethings awry? }
  92.                 end;
  93.         end; {case}
  94.       end; { Mono_Monitor }
  95.  
  96.  
  97.     begin { Demo_Intr }
  98.       if Mono_Monitor then
  99.         Move(Mem[$B000:$0000],hold_vid,4000)  {Save current video screen.}
  100.       else
  101.         Move(Mem[$B800:$0000],hold_vid,4000);
  102.       hold_x := WhereX; hold_y := WhereY;      {Save cursor position.}
  103.       ClrScr; GoToXY(1,12);
  104.       WriteLn('Control has been transferred to this memory resident program');
  105.       WriteLn('via the interrupt facility provided by MS-DOS.'); WriteLn;
  106.       WriteLn('When you press a key, control will revert back to the program');
  107.       WriteLn('that was suspended in order to process this interrupt.');
  108.       Write('Press ANY KEY ',ARROW); Read(Kbd,inchr);
  109.       if Mono_Monitor then
  110.         Move(hold_vid,Mem[$B000:$0000],4000)  {Restore current video screen.}
  111.       else
  112.         Move(hold_vid,Mem[$B800:$0000],4000);
  113.       GoToXY(hold_x,hold_y);                   {Restore the cursor.}
  114.     end; { Demo_Intr }
  115.  
  116.   procedure Save_Turbo_Values; { Store the data segment, stack segment and
  117.                                  stack pointer addresses in the resident
  118.                                  code segment using typed constants. }
  119.  
  120.     begin
  121.       new_dseg := Dseg;              { Save Dseg          }
  122.       new_sseg := Sseg;              { Save Sseg          }
  123.       inline($2E/$89/$26/new_sp);    { MOV [cs:new_sp],sp }
  124.     end;  { Save_Turbo_Values }
  125.  
  126.   procedure Interrupt;
  127.  
  128. { ***** This is the entry point for the interrupt handler ***** }
  129.  
  130.     begin
  131.       inline($2E/$8C/$16/hold_sseg/ { Save current Sseg }
  132.              $2E/$89/$26/hold_sp/   { Save current sp }
  133.              $2E/$8E/$16/new_sseg/  { Point Sseg to new stack seg.}
  134.              $2E/$8B/$26/new_sp);   { Points sp to new TOS }
  135.  
  136.       inline($50/$53/$51/$52/$57/$56/$06/$1E); { PUSH ax, bx, cx, dx,
  137.                                                       di, si, es, ds }
  138.  
  139.       inline($2E/$A1/new_dseg/      { MOV ax,[cs:new_dseg] }
  140.              $8E/$D8/               { MOV ds,ax      Point to new ds }
  141.              $FB);                  { STI }
  142.  
  143.       Demo_Intr; { This may be replaced with any defined procedure identifier }
  144.  
  145.       inline($FA/                             { CLI }
  146.              $1F/$07/$5E/$5F/$5A/$59/$5B/$58/ { POP  ds, es, si, di,
  147.                                                      dx, cx, bx, ax }
  148.              $2E/$8E/$16/hold_sseg/           { MOV  ss,[cs:hold_sseg] }
  149.              $2E/$8B/$26/hold_sp/             { MOV  sp,[cs:hold_sp] }
  150.              $5D/$5D/$CF);                    { POP return addr and IRET }
  151.  
  152.     end; { Interrupt }
  153.  
  154. {  The main program starts here. Its purpose is to install the address
  155.    of Interrupt in the interrupt vector table as interrupt $80 and to
  156.    allocate enough memory to make the program memory resident. When
  157.    executed it will produce no visible results unless interrupt $80
  158.    is already used. }
  159.  
  160. begin { Demonstrate_Interrupt_Handler }
  161.   Save_Turbo_Values;   { So you can set up the environment in Interrupt. }
  162.   FillChar(regs,SizeOf(regs),ZERO);  { Just to be safe. }
  163.   with regs do
  164.   begin
  165.  
  166. { Check to see if interrupt has already been installed using DOS Fn $35. }
  167.  
  168.     ah := $35;  al := INTR_VECTOR; MsDos(regs);
  169.     if es <> $00 then
  170.       begin
  171.         WriteLn(' Interrupt handler already installed.');
  172.         halt;                       { Quit if already installed }
  173.       end;
  174.  
  175. {  Install Interrupt procedure address at interrupt vector INTR_VECTOR.
  176.    using DOS Fn $25. }
  177.  
  178.     ah := $25; al := INTR_VECTOR;
  179.     ds := Cseg; dx := Ofs(Interrupt);
  180.     MsDos(regs);
  181.  
  182. { Make program memory resident reserving memory indicated by mem_size using
  183.   DOS Fn $31. }
  184.  
  185.     ax := $3100; dx := mem_size;  MsDos(regs);
  186.   end;  {with}
  187. end. { Demonstrate_Interrupt_Handlers }
  188.