home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / 554 / JUIN / TESTINT.PAS < prev    next >
Pascal/Delphi Source File  |  1993-10-07  |  3KB  |  96 lines

  1. {─ Fido Pascal Conference ────────────────────────────────────────────── PASCAL ─
  2. Msg  : 512 of 587
  3. From : Sean Palmer                         1:104/130.0          04 Jun 93  02:42
  4. To   : All
  5. Subj : State-Driven Interrupts
  6. ────────────────────────────────────────────────────────────────────────────────
  7. I just got this working, so have fun, guys!! 8)}
  8.  
  9. {by Sean L. Palmer}
  10. {Public Domain}
  11.  
  12. {This is a 'multitasking' program in the sense that it hooks into
  13.  the timer interrupt, but what that interrupt ends up actually
  14.  doing is controlled by the current value in SaveAdr, which
  15.  changes with each interrupt as the routine passes control back
  16.  to the tick handler not by exiting normally, but by an explicit
  17.  transfer of control.}
  18. {The end result of this is that you can write a state-driven
  19.  interrupt handler}
  20. {The included example is REALLY simplistic, and barely tested.
  21.  I intend to use this to write a comm port driver that
  22.  parses the incoming data as it receives it which would
  23.  be nice in a communications program that shells to dos, as
  24.  the incoming chars could be saved to disk in the background
  25.  with buffered ZModem or something...}
  26.  
  27. program intTest;
  28.  
  29. uses dos;
  30.  
  31. var saveAdr:word;  {offset in this code segment of where we are now}
  32. var active:boolean;  {to avoid re-entrancy}
  33.  
  34. procedure intHandler; far; assembler; asm
  35.  pusha
  36.  mov ax,seg @DATA
  37.  mov ds,ax
  38.  
  39.  {anything you need to do before continuing (reading port data?), do here}
  40.  
  41.  in al,$61  {click speaker as an example}
  42.  xor al,2
  43.  out $61,al
  44.  
  45.  test active,$FF  {exit now if interrupted ourselves}
  46.  jz @OK
  47.  popa
  48.  iret
  49.  
  50. @OK:
  51.  inc byte ptr active
  52.  sti
  53.  jmp [saveAdr]  {near jump to continue where handler last left off}
  54.  end;
  55.  
  56. {call this procedure from StateHandler to suspend execution until next time}
  57.  
  58. procedure wait; near; assembler; asm {wait for next interrupt}
  59.  pop word ptr saveAdr  {save where to continue next time}
  60.  dec byte ptr active
  61.  popa                  {restore caller regs}
  62.  iret
  63.  end;
  64.  
  65. const c:char='.';
  66.  
  67. procedure stateHandler; begin
  68.  
  69. {a stateHandler procedure should never ever exit (only by calling 'wait'),
  70.  shouldn't have any local variables or parameters, and shouldn't call
  71.  'wait' with anything on the stack (like from a subroutine).
  72.  This routine is using the caller's (interrupted program's) stack, so be
  73.  very very careful}
  74.  
  75.  asm pop bp; end;  {clean up stack mess left by Turbo's procedure header}
  76. {^ alternative method here is to init saveAdr to offset(proc)+3 and skip
  77.  the push bp; mov bp,sp altogether}
  78.  
  79.  repeat  {this is an example only}
  80.   c:='@';
  81.   wait;
  82.   c:='.';
  83.   wait;
  84.   until false;                {don't let it return normally!!}
  85.  end;
  86.  
  87. var oldHook:procedure;
  88. var i:integer;
  89.  
  90. begin
  91.  saveAdr:=ofs(stateHandler);
  92.  getIntVec($1C,@oldHook);
  93.  setIntVec($1C,@intHandler);
  94.  for i:=1 to 1500 do write(c);
  95.  setIntVec($1C,@oldHook);
  96.  end.