[Back to INTERRUP SWAG index] [Back to Main SWAG index] [Original]

    {
    > One part of the program I am writing must call an interrupt (6A I believe
    > - it is a networking interrupt).  The interrupt expects ds:dx to point to a
    > structure I have to create.  I know my procedures work because I have
    > tested them in real mode.  The problem comes when Is witch into protected
    > mode.  The interrupt can no longer find the record that I create. How can I
    > do this without too much trouble?  I was thinking of using a known segment,
    > such as SegB000 (which I am not using right now), and using memcpy to
    > copy the record I create to that segment.  Then I could just point ds:
    > SegB000 and dx: 0 and do my interrupt.

    Here's the unit I use to solve such problems. What you need to do :
    - allocate memory in the first megabyte, using AllocateLowMem,
    - properly set-up your structure in this memory area, using ProtectedPtr,
    - set-up a TRealModeRegs, DS being initialized with the RealSegment of
      the previously allocated memory block,
    - call your interrupt with RealModeInt.

    From: zlika@chaos2.frmug.fr.net (Raphael Vanney)
    }

    { Outils DPMI }
    {$x+,g+}

    {$IfNDef DPMI}
         You don't need that unit.
    {$EndIf}

    Unit MinDPMI ;

    Interface

    Type TRealModeRegs =
         Record
              Case Integer Of
              0: ( EDI, ESI, EBP, EXX, EBX, EDX, ECX, EAX: Longint;
                   Flags, ES, DS, FS, GS, IP, CS, SP, SS: Word) ;
              1: ( DI,DIH, SI, SIH, BP, BPH, XX, XXH: Word;
                   Case Integer of
                     0: (BX, BXH, DX, DXH, CX, CXH, AX, AXH: Word);
                     1: (BL, BH, BLH, BHH, DL, DH, DLH, DHH,
                         CL, CH, CLH, CHH, AL, AH, ALH, AHH: Byte));
         End ;

         TLowMemoryBlock     =
         { TLowMemoryBlock is used to point to a memory area within the
           first megabyte, which can thus be accessed both in protected
           and real mode. }
         Record
              ProtectedPtr   : Pointer ;    { pointer valid in protected mode }
              RealSegment    : Word ;       { segment valid in real mode (ofs=0) }
              Size           : Word ;       { size of allocated memory area }
         End ;

    Procedure ClearRegs(Var RealRegs : TRealModeRegs) ;

    Function RealModeInt(    IntNo          : Byte ;
                             Var RealRegs   : TRealModeRegs) : Boolean ;
    { Important notes :
      . If SS and SP are set to 0, the DPMI server will provide a 30 bytes stack.
      . Calling ClearRegs before initializing registers used for a RealModeInt
        sets SS ans SP to 0.
      }

    Procedure AllocateLowMem(Var Pt : TLowMemoryBlock ; Size : Word) ;
    Procedure FreeLowMem(Var Pt : TLowMemoryBlock) ;

    Procedure SetProtectedIntVec(No : Byte ; p : Pointer) ;
    Procedure GetProtectedIntVec(No : Byte ; Var p : Pointer) ;

    Implementation

    Uses WinAPI ;

    Type TDouble   =
         Record
              Lo, Hi    : Word ;
         End ;

    Procedure ClearRegs ;
    Begin
         FillChar(RealRegs, SizeOf(RealRegs), 0) ;
    End ;

    Function RealModeInt(    IntNo          : Byte ;
                             Var RealRegs   : TRealModeRegs) : Boolean ;
    Assembler ;
    Asm
         Mov  AX, $0300
         Mov  BL, IntNo
         XOr  BH, BH
         XOr  CX, CX
         LES  DI, RealRegs
         Int  $31
         Mov  AX, 0               { don't use XOr }
         JNC  @Ok
         Inc  AX
    @Ok:
         Or   AX, AX
    End ;

    Procedure AllocateLowMem ;
    Var  Adr  : LongInt ;
    Begin
         Adr:=GlobalDOSAlloc(Size) ;
         If Adr=0 Then Size:=0 ;
         Pt.ProtectedPtr:=Ptr(TDouble(Adr).Lo, 0) ;
         Pt.RealSegment:=TDouble(Adr).Hi ;
         Pt.Size:=Size ;
    End ;

    Procedure FreeLowMem ;
    Begin
         GlobalDOSFree(Seg(Pt.ProtectedPtr^)) ;
         FillChar(Pt, SizeOf(Pt), 0) ;           { Fills with NIL }
    End ;

    Procedure SetProtectedIntVec(No : Byte ; p : Pointer) ; Assembler ;
    Asm
         Mov  AX, $0205
         Mov  BL, No
         Mov  CX, TDouble[p].Hi        { Selector }
         Mov  DX, TDouble[p].Lo        { Offset }
         Int  $31
    End ;

    Procedure GetProtectedIntVec(No : Byte ; Var p : Pointer) ; Assembler ;
    Asm
         Mov  AX, $0204
         Mov  BL, No
         Int  $31
         LES  DI, p
         { Mov  ES:[DI], DX }
         { Mov  ES:[DI+2], CX }
         Mov  TDouble[ES:DI].Lo, DX
         Mov  TDouble[ES:DI].Hi, CX
    End ;

    Function  HugeAdr(Slct : Word ; Ofst : LongInt) : Pointer ;
    Assembler ;
    Asm
         Mov  AX, SelectorInc
         Mul  TDouble[Ofst].Hi
         Add  AX, Slct                 { First selector of bloc }
         Mov  DX, AX                   { New selector }
         Mov  AX, TDouble[Ofst].Lo     { Low word of offset is the same }
    End ;

    End.

[Back to INTERRUP SWAG index] [Back to Main SWAG index] [Original]