[Back to WIN-OS2 SWAG index] [Back to Main SWAG index] [Original]

    {
    >What you *can* do is these things.

    >1. You can modify the limit of a selector from $0000FFFF to
    >   $xxxxFFFF so assembler code can use 32-bit addressing.
    >   Note that you may not change the lower 16-bit of the limit
    >   field, or else the DPMI server crashes.

    >2. You can compile a 32-bit assembler procedure into your
    >   program.  It just needs a tiny (16 byte) wrapper and must
    >   reside in the low 64K of a segment (or else interrupts
    >   cannot return correctly).  However, the BP linker does
    >   not support 32-bit fixups so there are limits as to what
    >   you can put into the assembler code.

    >3. If you are willing to give up assembler access to BP
    >   variables, then you can make a binary image and link
    >   that into your program.  Then you can do whatever pleases
    >   you in the assembler procedure.

    >If there is interrest, I could post an example routine showing
    >this.

    Three files are needed: a batch file for assembly, an assembler
    file with 32-bit code, and a pascal test program.  The test
    program is not supposed to do anything useful.

    The code is unsupported.  You must know what you're doing.
    You'll need the `exe2bin' or `exetobin' utility; you'll need
    BP7 (with Turbo Assembler, and you cannot use TP7).  You must
    be using Borland's DPMI or some DPMI that supports 32-bit
    programs.  Don't even think about running this on a 286.  When
    things go wrong it's not my fault.  Don't tell me you know a
    better way to get the segment limit, because so do I.

    Morten Welinder
    terra@diku.dk

    { THE BATCH FILE }
    { CUT HERE }
    {***************************************************************************}

    @Echo Off
    Tasm /M2 /T /L Test32
    If Not Exist Test32.Obj Goto End
    Tlink /x test32 >Nul
    Exe2bin Test32.Exe Test32.Bin
    Rem Del Test32.Exe
    Del Test32.Obj
    :End

    { THE ASSEMBLER PROGRAM }
    { CUT HERE }
    {***************************************************************************}

    ; ---------------------------------------------------------------------------
    ; Example 32 bit program for use with Borland Pascal 7.0
    ; ---------------------------------------------------------------------------
    Ideal                                  ; (Keep Tasm happy)
    P386
    Model Use32 Huge,Pascal
    Segment Code Use32
    Assume  Cs:Code
    ; ---------------------------------------------------------------------------
    Entry0:  Movzx Eax,[Word Esp]          ; Change the stack frame to 32 bits
             Shr   [Dword Esp],16          ; so [Esp+xxx] works as expected.
             Push  Eax
             Jmp   P0
    Align 10h
    Entry1:  Movzx Eax,[Word Esp]          ; Aligned 10h for speed.
             Shr   [Dword Esp],16
             Push  Eax
             Jmp   P1
    Align 10h
    Entry2:  Movzx Eax,[Word Esp]          ; Aligned 10h for speed.
             Shr   [Dword Esp],16
             Push  Eax
             Jmp   P2
    ; etc.
    ; ---------------------------------------------------------------------------
    Align 10h
    Proc P0 Far L1:Dword,L2:Dword
             Mov   Eax,[L1]                ; Add the parameters
             Add   Eax,[L2]

             Shld  Edx,Eax,16              ; Output is left in Dx:Ax
             Ret
    Endp
    ; ---------------------------------------------------------------------------
    Align 10h
    Proc P1 Far
             Push  Ds                      ; Call MsDos from a 32 bit segment
             Mov   Ax,Cs                   ; Never ever perform a software
             Mov   Ds,Ax                   ; interrupt if Ip>=64K!
             Mov   Ah,9
             Mov   Edx,Offset Message
             Int   21h
             Pop   Ds
             Ret

    Message  Db    'Hello, 32 bit world!',13,10,'$'
    Endp
    ; ---------------------------------------------------------------------------
    Align 10h
    Proc P2 Far P:Dword
             Push  Ds
             Xor   Esi,Esi
             Lds   Si,[Small P]
             Mov   Ecx,20000h/4
      @@1:   Mov   [Esi],Esi
             Add   Esi,4
             Loop  @@1
             Pop   Ds
             Ret
    Endp
    ; ---------------------------------------------------------------------------
    Ends
    End

    { THE TEST PROGRAM }
    { CUT HERE }
    {***************************************************************************}

    Program   Test;
    { ------------------------------------------------------------------------- }
    Uses      Winapi, Dos;
    { ------------------------------------------------------------------------- }
    Const     Dpmi_32BitSegment           = $4000;

    Type      Dpmi_Descriptor             = Record
                Limit0015                 : Word;
                Base0015                  : Word;
                Base1623                  : Byte;
                Rights                    : Byte;   { 7=Prsnt, 6-5=Dpl, 4=App,  }
                                                    { 3-0=Type                  }
                Rights386                 : Byte;   { 7=Gran, 6=Size32, 5=0,    }
                                                    { 4=Avail, 3-0=Limit1619    }
                Base2431                  : Byte;
                End;

    Var       Sel      : Word;
              Oldright : Word;
              ProcPtr  : Pointer;
              P1       : Function(L1,L2: LongInt): LongInt;
              P2       : Procedure;
              P3       : Procedure(P: Pointer);
              Fil      : File;
              Data     : Pointer;
              Dsel     : Word;
    { ------------------------------------------------------------------------- }
    Procedure Dpmi_SetSelectorLimit(Sel: Word; Limit: LongInt); Assembler;
    Asm    Mov   Ax,0008H
           Mov   Bx,[Sel]
           Mov   Dx,[Word Ptr Limit]
           Mov   Cx,[Word Ptr Limit+2]
           Int   31H
    End;
    { ------------------------------------------------------------------------- }
    Procedure Dpmi_GetDescriptor(Sel: Word; Var Buffer: Dpmi_Descriptor); Assembler;
    Asm    Mov   Ax,000Bh
           Mov   Bx,[Sel]
           Les   Di,[Buffer]
           Int   31H
    End;
    { ------------------------------------------------------------------------- }
    Procedure Dpmi_SetDescriptor(Sel: Word; Var Buffer: Dpmi_Descriptor); Assembler;
    Asm    Mov   Ax,000Ch
           Mov   Bx,[Sel]
           Les   Di,[Buffer]
           Int   31H
    End;
    { ------------------------------------------------------------------------- }
    Function  Dpmi_GetAccessRights(Sel: Word): Word; Assembler;
    Var       Buffer : Dpmi_Descriptor;
    Asm    Mov   Bx,[Sel]
           Push  Bx
           Push  Ss
           Lea   Di,[Buffer]
           Push  Di
           Call  Dpmi_GetDescriptor
           Mov   Ax,[Word Ptr Buffer+5]
    End;
    { ------------------------------------------------------------------------- }
    Procedure Dpmi_SetAccessRights(Sel: Word; Rights: Word); Assembler;
    Var       Buffer : Dpmi_Descriptor;
    Asm    Mov   Bx,[Sel]
           Lea   Di,[Buffer]
           Push  Bx
           Push  Ss
           Push  Di
           Push  Bx
           Push  Ss
           Push  Di
           Call  Dpmi_GetDescriptor
           Mov   Ax,[Word Ptr Buffer+5]
           And   Ax,8F00h
           Mov   Bx,[Rights]
           And   Bx,50Ffh
           Or    Ax,Bx
           Mov   [Word Ptr Buffer+5],Ax
           Call  Dpmi_SetDescriptor
    End;
    { ------------------------------------------------------------------------- }
    Function  Dpmi_GetSelectorLimit(Sel: Word): LongInt; Assembler;
    Var       Buffer : Dpmi_Descriptor;
    Asm    Mov   Bx,[Sel]
           Push  Bx
           Push  Ss
           Lea   Di,[Buffer]
           Push  Di
           Call  Dpmi_GetDescriptor
           Mov   Dx,[Word Ptr Buffer+6]
           Mov   Ax,[Word Ptr Buffer]
           Test  Dl,80H
           Je    @@3
           Mov   Bx,Ax
           Mov   Cl,4
           Shr   Bx,Cl
           Mov   Cl,12
           Shl   Dx,Cl
           Shl   Ax,Cl
           Or    Dx,Bx
           Or    Ax,0Fffh
           Jmp   @@2
      @@3: And   Dx,0Fh
           Jmp   @@2
      @@1: Mov   Ax,0
           Mov   Dx,0
      @@2:
    End;
    { ------------------------------------------------------------------------- }
    Function Int2HexN(L: LongInt; N:Integer): String;
    Const    Digits : Array[0..15] Of Char = '0123456789ABCDEF';
    Var      S : String;
    Begin
      S:='';
      While N>0 Do Begin
        S:=Digits[L And $F]+S;
        Dec(N);
        L:=L Shr 4;
      End;
      Int2HexN:=S;
    End;
    { -------------------------------------------------------------------------- }

    Begin
      Data:=GlobalallocPtr(Gmem_Zeroinit,$20000);
      Dsel:=Seg(Data^);
      Dpmi_SetSelectorLimit(Dsel,$1FFFF);

      GetMem(ProcPtr,$4000);
      Assign(Fil,'Test32.Bin');
      Reset(Fil,1);
      BlockRead(Fil,ProcPtr^,FileSize(Fil));
      Close(Fil);
      LongInt(@P1):=(LongInt(ProcPtr)+0*16);
      LongInt(@P2):=(LongInt(ProcPtr)+1*16);
      LongInt(@P3):=(LongInt(ProcPtr)+2*16);

      Sel:=Seg(ProcPtr^);
      Oldright:=Dpmi_GetAccessRights(Sel);
      Dpmi_SetAccessRights(Sel,(Oldright Or Dpmi_32BitSegment) And $FFF1+$A);

      Writeln('Proc:   ',Int2HexN(Sel,4),':',Int2HexN(Ofs(ProcPtr^),8));
      Writeln('Base:   ',Int2HexN(Getselectorbase(Sel),8));
      Writeln('Limit:  ',Int2HexN(Dpmi_GetSelectorLimit(Sel),8));
      Writeln('Rights: ',Int2HexN(Dpmi_GetAccessRights(Sel),4));
      Writeln;
      Writeln('Data:   ',Int2HexN(Seg(Data^),4),':',Int2HexN(Ofs(Data^),8));
      Writeln('Base:   ',Int2HexN(Getselectorbase(Dsel),8));
      Writeln('Limit:  ',Int2HexN(Dpmi_GetSelectorLimit(Dsel),8));
      Writeln('Rights: ',Int2HexN(Dpmi_GetAccessRights(Dsel),4));
      Writeln;
      Writeln('Ss:Sp:  ',Int2HexN(SSeg,4),':',Int2HexN(SPtr,4));

      Writeln('Result: ',Int2HexN(P1($12345678,$87654321),8));
      P2;
      P3(Data);

      Dpmi_SetAccessRights(Sel,Oldright);
      Dpmi_SetSelectorLimit(Dsel,$FFFF);
      GlobalfreePtr(Data);
    End.

[Back to WIN-OS2 SWAG index] [Back to Main SWAG index] [Original]