home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1992 / 20 / umb_heap / umb_heap.pas next >
Pascal/Delphi Source File  |  1992-05-25  |  4KB  |  163 lines

  1. UNIT UMB_Heap;
  2. (**) INTERFACE (**)
  3. CONST Max_Blocks = 4;
  4.   { It's not likely more than 4 UMBs are needed }
  5. TYPE
  6.   UmbDataType = Array[1..Max_Blocks] of Word;
  7.  
  8.   PROCEDURE Extend_Heap;
  9.   { Use Upper Memory Blocks to extend the heap }
  10.   PROCEDURE GetBlockSizes(VAR US : UmbDataType);
  11.  
  12. (**) IMPLEMENTATION (**)
  13.  
  14. TYPE
  15. {  From pg. 216 of the TP6 programmer's guide.  }
  16. {  It's used for traversing the free blocks of  }
  17. {  the heap.                                    }
  18.   PFreeRec = ^TFreeRec;
  19.   TFreeRec = RECORD          
  20.     Next : PFreeRec;         
  21.     Size : Pointer;
  22.   END;
  23.  
  24. VAR
  25.   Block_Segments : UmbDataType;
  26.     { UMB starting segments }
  27.   Block_Sizes    : UmbDataType;
  28.     { UMB sizes             }
  29.   SaveExitProc : Pointer;
  30.  
  31. FUNCTION UMB_Driver_Present : Boolean;
  32.   { See if a UMB-capable driver is present. }
  33. VAR Flag : Boolean;                        
  34. BEGIN
  35.   Flag := False;
  36.   ASM
  37.     mov ax,$4300
  38.     int $2F
  39.     cmp al,80h
  40.     jne @Done
  41.     inc [Flag]
  42.   @Done:
  43.   END;
  44.   UMB_Driver_Present := Flag;
  45. END;
  46.  
  47. PROCEDURE Allocate_UMB;
  48. { Add the four largest UMBs to the heap }
  49. VAR
  50.   i,
  51.   Save_Strategy,
  52.   Block_Segment,
  53.   Block_Size : Word;
  54. BEGIN
  55.   FOR i := 1 to Max_Blocks DO
  56.   { Assume that no blocks will be selected }
  57.     BEGIN
  58.       Block_Segments[i] := 0;
  59.       Block_Sizes[i] := 0;
  60.     END;
  61.   ASM
  62.     mov ax,5801h
  63.     mov bx,0040h
  64.     int 21h       { Set the DOS allocation strategy to }
  65.     mov ax,5803h  { uses only high memory              }
  66.     mov bx,0001h
  67.     int 21h       { Set the UMB status to add UMBs }
  68.   END;
  69.   FOR i := 1 to Max_Blocks DO
  70.     BEGIN
  71.       Block_Segment := 0;
  72.       Block_Size := 0;
  73.       ASM
  74.         mov ax,4800h
  75.         mov bx,0FFFFh
  76.         int 21h  { Get the size of the next largest UMB }
  77.         cmp bx,0
  78.         je @Fail
  79.         mov ax,4800h
  80.         int 21h              { Get the next largest UMB }
  81.         jc @Fail
  82.         mov [Block_Segment],ax
  83.         mov [Block_Size],bx
  84.       @Fail:
  85.       END;
  86.       { Save the UMB's size and addr }
  87.       Block_Segments[i] := Block_Segment;
  88.       Block_Sizes[i] := Block_Size;
  89.     END;
  90. END;
  91.  
  92. PROCEDURE Release_UMB; FAR;
  93. { Exit PROCEDURE to release UMBs }
  94. VAR
  95.   i,
  96.   Segment : Word;
  97. BEGIN
  98.   ExitProc := SaveExitProc;
  99.   ASM
  100.     mov ax,5803h
  101.     mov bx,0000h
  102.     int 21h  { Set the UMB status to release UMBs }
  103.   END;
  104.   FOR i := 1 to Max_Blocks DO
  105.     BEGIN
  106.       Segment := Block_Segments[i];
  107.       IF (Segment > 0) THEN
  108.         ASM
  109.           mov ax,$4901
  110.           mov bx,[Segment]
  111.           mov es,bx
  112.           int 21h               { Release the UMB }
  113.         END;
  114.     END;
  115. END;
  116.  
  117. FUNCTION Pointer_To_LongInt(P : Pointer) : LongInt;
  118. TYPE
  119.   PtrRec = RECORD
  120.     Lo, Hi : Word;
  121.   END;
  122. BEGIN
  123.   Pointer_To_LongInt :=
  124.     LongInt(PtrRec(P).Hi)*16+PtrRec(P).Lo;
  125. END;
  126.  
  127. PROCEDURE Extend_Heap;
  128. VAR
  129.   i    : Word;
  130.   Temp : PFreeRec;
  131. BEGIN
  132.   IF UMB_Driver_Present THEN
  133.     BEGIN
  134.       Allocate_UMB;
  135.       Temp := HeapPtr;
  136.       i := 1;
  137.       WHILE ((Block_Sizes[i] > 0) AND
  138.              (i <= Max_Blocks)) DO
  139.         BEGIN
  140.           Temp^.Next := Ptr(Block_Segments[i],0);
  141.           Temp       := Temp^.Next;
  142.           Temp^.Next := HeapPtr;
  143.           Move(Block_Sizes[i], Temp^.Size,SizeOf(Word));
  144.           Temp^.Size := Pointer(LongInt(Temp^.Size)
  145.             SHL 16);
  146.           Inc(i);
  147.         END;
  148.       IF (Block_Sizes[1] > 0) THEN
  149.         FreeList := Ptr(Block_Segments[1], 0);
  150.     END;
  151. END;
  152.  
  153. PROCEDURE GetBlockSizes(VAR US : UmbDataType);
  154. BEGIN
  155.   US := Block_Sizes;
  156. END;
  157.  
  158. BEGIN
  159.   FillChar(Block_Sizes, SizeOf(Block_Sizes), 0);
  160.   SaveExitProc := ExitProc;
  161.   ExitProc := @Release_UMB;
  162. END.
  163.