[net.micro.pc] Error in Turbo-Pascal?

vr0z05@unido.UUCP (04/04/85)

Hello folks,

is there anybody in net-land who is able to help me?
the following program will not work, but why not?
(TURBO-PASCAL V.2.0 on IBM-PC/XT)

>PROGRAM TEST;
>type REGPACK = record
>                  AX,BX,CX,DX,BP,SI,DI,DS,ES,FLAGS : integer;
>               end;
>var RECPACK : REGPACK;
>procedure INTR_TEST;
>begin
>   inline($FB/$CF) {STI/IRET}
>end;
>begin
>   RECPACK.AX := ($25 shl 8) + $50;
>   RECPACK.DS := cseg;
>   RECPACK.DX := ofs(INTR_TEST);
>   intr($21,RECPACK);
>   intr($50,RECPACK);
>end.

The program starts correct, changes the interrupt-vector $50 to the address
of INTR_TEST, then calls via INT the procedure INTR_TEST and executes it
(until now nothing wrong), but after that the program hangs (no BREAK,
no RESET will work, only POWER OFF/ON).

Helpfull hints to

Uwe Hoch
University of Dortmund
Computer Science Department(IRB)
P.O. Box 500500
D-4600 Dortmund 50
West-Germany

via mail or uucp.

Thanks in advance!

stekas@hou2g.UUCP (J.STEKAS) (04/08/85)

Here are several tips in writing interupt handling routines for
MS-DOC PCs using TURBO Pascal.  There have been several requests.

1) TURBO begins each procedure with from 6-8 bytes of stack pointer
   manipulations.  This makes the location of the first line of code
   hard to find.  The solution is to pad the beginning of the 
   interupt routine with a bunch of NOPs and set the interupt vector
   in the middle.

2) The manual give INLINE statements to save and restore registers
   at the entry and exit of your routine.  What it doesn't tell
   you is that you must also save DS, *set* it, and restore it upon
   exit.  This must be done in case an interupt occurs while a system
   function is being executed and DS does not point to the TURBO data
   segment.
   
The code looks something like this:

{ Globals }
type  AnyPtr = ^Integer ;
var   MyDSegPtr : AnyPtr ;        { Will point to MyDseg }
const MyDSeg : Integer =  $1111 ;   { Value will be reset  }
    
Procedure IntHand ;
begin
  INLINE($90/$90/$90/$90/$90/$90) ;  { Wide NOP Target }
  INLINE( Borland's entry inline ) ;
  INLINE( $1E/                   {  push ds  }
          $2E/$A1/MyDSeg/        {  mov  ax, cs:MyDSeg }
          $8E/D8 ) ;             {  mov  ds, ax }
  { Your Code here }
  INLINE($1F);                   { pop DS }
  INLINE( Borland's Exit ) ;
end;
Procedure SetUp ;
var TableEnt : ^AnyPtr ; 
begin
  MyDSegPtr  := Addr( MyDSeg ) ;
  MyDSegPtr^ := DSEG ;           { We have reset the constant! }
  TableEnt   := Ptr($00,$10)   ; { ^vector table entry }
  TableEnt^  := Ptr(Cseg, Ofs(IntHand)+10) ; { Point into NOPs }
end;
   
Hope this helps some of you.         - Jim  ihnp4!hou2g!stekas