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

    {
    MAX MAISCHEIN

    > Yes, but my question deals with storage in the Heap - I want to load
    > and manipulate as much data in memory as possible.  Hence, I am looking
    > for 1 byte improvements, if possible.  The actual file content size is
    > not an issue...

    For the case that some of your machines have UMBs available, I have a unit
    that extends the heap into these UMB blocks completely transparent.
    THe unit seems to work, I'd like to see any comments about bugs etc. on it.

        Max Maischein                                          2:249/6.17

        This unit was created to use the  high  memory  under  DOS  where
        LoadHi loads the TSRs etc. as extra heap. This was  possible  due
        to the revamped heap manager of Turbo  Pascal,  which  now  again
        uses MCBs to control its freelist instead of  an  array  of  8192
        pointers. I used this technique just like Himem / Quemm to insert
        a huge used block, the high DOS / BIOS area in the heap and  then
        to add the free RAN behind it. Now I have a maximum heap  size of
        700K, which is nicer than the old 640K  limit.  Note  that  using
        UseHi will not pay attention to the compiler $M settings in  your
        source. The memory is freed automatically by DOS, but  I  had  to
        adjust the MaxHeapxxx variable in the Memory unit, this is a word
        that contains the maximum heap size,  which  increased  by  using
        UseHi. If you don't need Turbo Vision, you can  remove  the  Uses
        Memory line and also remove the MaxHeapxxx adjustment.  But  with
        TVision, it will only work, if you have this line in it.

        The text variable HeapWalk is for debugging purposes, if you want
        to see a dump of the free blocks in the heap, you need to  assign
        and reset / rewrite the HeapWalk variable and then call ListWalk.
        Don't forget to close the HeapWalk variable again. It  will  dump
        the whole freelist into the file.

        This piece of code is donated to the public domain, but I request
        that, if you use this code, you mention me in the DOCs somewhere.

                                                                     -max
    }

    Unit UseHi;
    Interface

    Type
      PFreeRec = ^TFreeRec;
      TFreeRec = Record
        Next   : Pointer;
        Remain : Word;
        Paras  : Word;
      End;

    Var
      HeapWalk : ^Text;

    Procedure ListWalk;

    Var
      NewHeap : Pointer;
      NewSize : Word;

    Implementation
    Uses
      MemAlloc,
      Memory,
      Objects,
      Strings2;

    Const
      MemStrategy : Word = 0;
      UMBState    : Boolean = False;

    Procedure himem_Init; Assembler;
    Asm
      mov  ax, 5800h
      int  21h
      mov  MemStrategy, ax
      mov  ax, 5802h
      int  21h
      mov  UMBState, al
      mov  ax, 5803h
      mov  bx, 1
      int  21h
      mov  ax, 5801h
      mov  bx, 0040h
      int  21h
    End;

    Procedure himem_Done; Assembler;
    Asm
      mov  ax, 5801h
      mov  bx, MemStrategy
      int  21h
      mov  ax, 5803h
      mov  bl, UMBState
      xor  bh, bh
      int  21h
      mov  ax, 1
    End;

    Procedure MakeFreeList;
    Var
      Mem : LongInt;      { size of last block between heapPtr / HeapEnd }
      P   : PFreeRec;
    Begin
      If (NewHeap = nil) then
        Exit;

      P := HeapPtr;

      Mem := LongInt(PtrRec(HeapEnd).Seg) shl 4 + PtrRec(HeapEnd).Ofs;
      Dec(Mem, LongInt(PtrRec(HeapPtr).Seg) shl 4 + PtrRec(HeapPtr).Ofs);

      If (Mem < 8) then
        RunError(203);

      With P^ do
      Begin
        Next   := NewHeap;
        Paras  := Mem shr 4;
        Remain := Mem and $0F;
      End;

      HeapPtr := NewHeap;
      HeapEnd := NewHeap;
      With PtrRec(HeapEnd) do
        Inc(Seg, Pred(NewSize));
      MaxHeapSize := PtrRec(HeapEnd).Seg - PtrRec(HeapOrg).Seg;
    End;

    Function BlockSize(P : PFreeRec) : LongInt;
    Begin
      With P^ do
        BlockSize := LongInt(Paras) * 16 + LongInt(Remain);
    End;

    Procedure ListWalk;
    Var
      P   : PFreeRec;
      Mem : LongInt;
    Begin
      WriteLn(HeapWalk^, 'Free list    :', WPointer(FreeList));
      WriteLn(HeapWalk^, 'Heap end     :', WPointer(HeapEnd));
      WriteLn(HeapWalk^, 'Heap pointer :', WPointer(HeapPtr));
      WriteLn(HeapWalk^, 'New heap     :', WPointer(NewHeap));
      WriteLn(HeapWalk^, 'Walk of freelist :' );
      P := FreeList;
      If P <> HeapPtr then
        While P <> HeapPtr do
        Begin
          Write(HeapWalk^, WPointer(Addr(P^)), ' -- ');
          With PtrRec(P), P^ do
            Write(HeapWalk^, WPointer(Ptr(Seg + Paras, Ofs + Remain)));
          WriteLn(HeapWalk^, ', ', BlockSize(P) : 7, ' bytes.');
          P := P^.Next;
        End;
      Mem := LongInt(PtrRec(HeapEnd).Seg) shl 4 + PtrRec(HeapEnd).Ofs;
      Dec(Mem, LongInt(PtrRec(HeapPtr).Seg) shl 4 + PtrRec(HeapPtr).Ofs);
      WriteLn(HeapWalk^, WPointer(HeapPtr), ' -- ', WPointer(HeapEnd), ', ',
                         Mem : 7, ' bytes left on top of heap.');
    End;

    Begin
      NewHeap  := nil;
      HeapWalk := @Output;

      himem_Init;
      NewSize := DOSMemAvail shr 4;
      MAlloc(NewHeap, DosMemAvail);
      himem_Done;

      MakeFreeList;
    End.

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