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

{
  From: Andrew Eigus                                 Read: Yes    Replied: No

> Well, the subject says it, how can I get a 65536 Bytes hunk of memory?
> There has to be another way, maybe a dos call or something?

Yes. The following are routines to allocate memory using DOS functions,
the limitation is that HeapMin and HeapMax should be set both to zero like
this: {$M 8192,0,0}

Function DosMaxAvail : longint;
{$IFNDEF ProtectedMode}
assembler;
{ Returns the size of the largest contiguous free memory block
  This function should be called ONLY when both HeapMin/HeapMax
  memory allocation parameters set to zero }
Asm
  mov bx,0FFFFh
  mov ah,48h
  int 21h
  mov ax,bx
  mov bx,16
  mul BX
End;
{$ELSE}
Begin
  DosMaxAvail := GetFreeSpace(0) { uses WinAPI for DPMI }
End; { DosMaxAvail }
{$ENDIF}

Function DosGetMem(Size : longint) : pointer;
{ Creates a dynamic variable of the specified size and returns the pointer
  to it. This function should be called ONLY when both HeapMin/HeapMax
  memory allocation parameters set to zero. This function returns a pointer to
  allocated data buffer which can lie in different segments, or it returns
  a nil pointer if the dos call was unsuccessful; in that case, the
Dos.DosError variable keeps error code }{$IFNDEF ProtectedMode}
assembler;
Asm
@@1:
  mov DosError,0 { uses Dos }
  mov ax,word ptr [Size]
  mov dx,word ptr [Size+2]
  mov cx,16
  div cx
  inc ax
  mov bx,ax
  mov ah,48h
  int 21h
  jnc @@2
  mov DosError,ax { save error code in Dos.DosError variable }
  xor ax,ax { return nil pointer }
@@2:
  mov dx,ax { save segment }
  xor ax,ax { offset allways zero }
End;
{$ELSE}
Begin
  DosGetMem := GlobalAllocPtr(gmem_ZeroInit or gmem_Moveable, Size) { WinAPI }
End; { DosGetMem }
{$ENDIF}

Function DosFreeMem(P : pointer) : integer;
{ Disposes of a given dynamic variable. This function should be called ONLY
  when both HeapMin/HeapMax memory allocation parameters set to zero. This
  function returns non-zero DOS error code if the function failed, or zero
  if the call was successful }
{$IFNDEF ProtectedMode}
assembler;
Asm
  mov DosError,0 { set Dos.DosError to noerror }
  mov es,word ptr [P+2]
  mov ah,49h
  int 21h
  jnc @@1
  mov DosError,ax
End;
{$ELSE}
Begin
  DosFreeMem := GlobalFreePtr(P)
End; { DosFreeMem }
{$ENDIF}

Function DosRegetMem(P : pointer; NewSize : longint) : pointer;
{ Changes the size of an existing memory block. This function should be called
  ONLY when both HeapMin/HeapMax memory allocation parameters set to zero.
  It returns a nil pointer, if the call was unsuccessful, otherwise it returns
  a pointer to reallocated data buffer }
{$IFNDEF ProtectedMode}
assembler;
Asm
@@1:
  mov DosError,0 { using Dos unit still :) }
  mov ax,word ptr [NewSize]
  mov dx,word ptr [NewSize+2]
  mov cx,16
  div cx
  inc ax
  mov bx,ax
  mov ah,4Ah
  int 21h
  jnc @@2
  mov DorError,ax { save error code in DosError }
  xor ax,ax { return a nil pointer }
@@2:
  mov dx,ax
  xor ax,ax
End;
{$ELSE}
Begin
  DosRegetMem := GlobalReallocPtr(P, NewSize, gmem_ZeroInit or gmem_Moveable)
End; { DosRegetMem }
{$ENDIF}

Example:

  {$M 4096,0,0}
  var P : pointer;

  Begin
    P := DosGetMem(128 shl 10); { allocate 128k }
    if P = nil then
      WriteLn('It seems that you haven''t enough memory, eh?')
    else
    begin
      P := DosRegetMem(256 shl 10); { reallocate this block to 256k }
      if P = nil then
        WriteLn('No, 256k is too much! :-)')
    end;
    DosFreeMem(P)
  End.


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