[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]