======================================================
MPr...@mindspring.com
da...@medallioncabinetry.com
IIRC, MS-DOS uses al=49h/int21h to free memory, and al=48h to
allocate memory. These were seldom used except in TSR's because
usually by default all memory is allocated to the loaded code.
I don't know how Win32 does malloc().
For traditional Unix, malloc() is a lib c wrapper for sbrk() qv.
Linux may now be using mmap().
-- Robert
Under UNIX probably you would implement it using sbrk().
As far as writing your own memory allocator goes - these babies are not very
complex. Usually, however you would allocate more per block of memory than
requested size since there is some bookeeping to take care of. You might
have a list of all free blocks in memory, taken blocks might point to the
next ones etc. When implementing realloc you might also want to move
everything to the new block etc. if the initial one could not be reallocated
to the desired size (this is why you should not keep pointers in your
program to the block that might get realloc() called on it). Also note that
there are different strategies to allocate memory - you might want to go
for the firt block that is large enough for your requested size (which
might waste memory) as opposed to searching for the best one that fits your
needs (which might waste time).
There was a memory allocator implemented in K&R's C book I believe. But I am
sure you will stumble upon many source codes on the net.
Now if you will excuse me - I will change the Blues Brothers tape in my
walkman - been listening to it's two sides for the past four hours and I am
sick :)
Hope I helped.
Ognen
David Bringen <mpr...@mindspring.com> wrote in message
news:s9klrq...@corp.supernews.com...
>
> How do you accomplish malloc() (dynamic memory allocation) in assembler?
> Either MS-DOS platform or command prompt from Win95. Simple? Elaborate?
> Source code example somewhere? Please?
>
> ======================================================
> MPr...@mindspring.com
> da...@medallioncabinetry.com
>
>
IIRC, MS-DOS uses al=49h/int21h to free memory, and al=48h to
If you're running under DOS, I'd recommend getting a copy
of the UCR Standard Library for 80x86 Assembly Language
Programmers. It contains a bunch of memory management
routines including malloc and free. You can get a copy
from http://webster.cs.ucr.edu.
Under Windows, you can use GlobalAlloc et. al. to handle this.
I've included the code for the HLA malloc and free routines (as
well as others) so you can see how this call is done.
Randy Hyde
unit memory;
#include( "memory.hhf" );
#include( "x86.hhf" );
#include( "excepts.hhf" );
#include( "strings.hhf" );
const
Gmem_Fixed : dword := 0;
eaxOffset : text := "(type pushaRec [esp]).eaxOfs";
// malloc:
//
// Memory allocation. Calls Win32 GlobalAlloc routine
// with GMEM_FIXED attribute to allocate the storage.
//
// Returns pointer to allocated block in EAX (NULL=0 if
// allocation fails).
static
GlobalAlloc:procedure( size:dword; flags:dword );
external( "__imp__GlobalAlloc@8" );
GlobalFree:procedure( ptr:dword );
external( "__imp__GlobalFree@4" );
procedure GlobalReAlloc( Flags:dword; NewSize:dword; hMem:dword );
external( "__imp__GlobalReAlloc@12" );
procedure malloc( size:dword );
begin malloc;
pushad();
pushfd();
cld();
GlobalAlloc( size, Gmem_Fixed );
if( eax = 0 ) then
raise( ex.MemoryAllocationFailure );
endif;
popfd();
mov( eax, eaxOffset ); // Need to return the value in EAX.
popad();
end malloc;
procedure free( memptr:dword );
begin free;
pushad();
pushfd();
cld();
GlobalFree( memptr );
popfd();
popad();
end free;
// realloc:
//
// Reallocate a block of memory. Just calls the Win32 GlobalRealloc
// routine with the GMEM_FIXED flag.
//
// Returns pointer to reallocated block in EAX, NULL if allocation
// fails.
procedure realloc( memptr:dword; newsize:dword );
begin realloc;
pushad();
pushfd();
cld();
GlobalReAlloc( Gmem_Fixed, newsize, memptr );
if( eax = 0 ) then
raise( ex.MemoryAllocationFailure );
endif;
popfd();
mov( eax, eaxOffset ); // Need to return the value in EAX.
popad();
end realloc;
// stralloc:
//
// Allocate storage for an HLA string object.
// The size parameter specifies the number of characters.
// Must call malloc with size+8+? since we need to reserve space
// for the maxlen the curlen fields as well as space for a zero
// terminating byte. Note that HLA strings must always be dword
// aligned; this code depends upon the fact that GlobalAlloc always
// returns a pointer that is aligned on a 16-byte boundary in order
// to accomplish this. HLA strings are always an even multiple of
// 16 bytes long (including storage for the zero terminating byte).
// Hence the extra logic that *may* extend the size of the allocated
// storage.
procedure stralloc( size:dword );
begin stralloc;
pushad();
pushfd();
cld();
mov( size, eax );
add( 12, eax ); // 9 bytes for maxlen, curlen, and zero byte and
and( !3, eax ); // round up to next dword multiple.
GlobalAlloc( eax, Gmem_Fixed );
if( eax = 0 ) then
raise( ex.MemoryAllocationFailure );
endif;
mov( size, ebx ); // Get maxlen value.
mov( ebx, [eax] ); // Store into maxlen field of string object.
xor( ebx, ebx ); // Zero out ebx.
mov( ebx, [eax+4] ); // Current string length is zero.
mov( bl, [eax+8] ); // Zero terminate the string.
add( 8, eax ); // Return pointer to start of characters.
popfd();
mov( eax, eaxOffset ); // Need to return the value in EAX.
popad();
end stralloc;
procedure strrealloc( theStr:dword; size:dword );
begin strrealloc;
pushad();
pushfd();
cld();
mov( theStr, eax );
mov( size, ecx );
// If the new size is less than the current string length,
// raise a string overflow exception.
if( ecx < (type str.strRec [eax]).length ) then
raise( ex.StringOverflow );
endif;
// The size value passed as a parameter specifies the number of
// characters. It does not include the zero byte, length, or
// MaxLength values (nine bytes). Add in those nine bytes plus
// round the total length up to an even multiple of four bytes.
add( 12, ecx );
and( !3, ecx);
// Set new maximum length for the string.
mov( ecx, (type str.strRec [eax]).MaxStrLen );
// Realloc function wants the pointer to point at the start of the
// allocation. String pointers point eight bytes into the allocated
// data; adjust for that here.
sub( 8, eax );
GlobalReAlloc( Gmem_Fixed, ecx, eax );
if( eax = 0 ) then
raise( ex.MemoryAllocationFailure );
endif;
// Adjust the returned memory address so that it points at the
// start of the string data (rather than at the MaximumLength field).
add( 8, eax );
popfd();
mov( eax, eaxOffset ); // Need to return the value in EAX.
popad();
end strrealloc;
// strfree:
//
// Deallocates storage allocated via stralloc above.
// Parameter is a pointer to the string; this routine
// adjusts the pointer so that it points at the start of the
// block allocated by GlobalAlloc and then it calls GlobalFree.
procedure strfree( memptr: dword );
begin strfree;
pushad();
pushfd();
cld();
sub( 8, memptr );
free( memptr );
popfd();
popad();
end strfree;
end memory;
> If you're running under DOS, I'd recommend getting a copy
> of the UCR Standard Library for 80x86 Assembly Language
> Programmers. It contains a bunch of memory management
> routines including malloc and free. You can get a copy
> from http://webster.cs.ucr.edu.
You know, I've been trying to tap into this site, but I always bomb out.
Maybe it's just too damn popular.
>...I've included the code for the HLA malloc and free routines (as
> well as others) so you can see how this call is done.
> Randy Hyde
>...
Lovely! Thanks a lot.
======================================================
MPr...@mindspring.com
da...@medallioncabinetry.com
Knuth? Don't know this one. Time to crank up AltaVista. Thanks for the
lead. :-)
======================================================
MPr...@mindspring.com
da...@medallioncabinetry.com
You did. But surprisingly, I've had a devil of a time finding assembler
source code that does mem management. Maybe because DOS routines aren't
expected to cope with dynamic memory allocation?
Now if you'll excuse ME, there's a new "Mike, Lu & Og" on. :-)
======================================================
MPr...@mindspring.com
da...@medallioncabinetry.com
>How do you accomplish malloc() (dynamic memory allocation) in assembler?
>Either MS-DOS platform or command prompt from Win95. Simple? Elaborate?
>Source code example somewhere? Please?
>
Except for large blocks, segments really, DOS doesn't do dynamic
memory allocation. You have to define a heap yourself. I've got some
very sparsely commented sourcecode for HeapInit, Malloc, Calloc,
ReAlloc and Free that I copied from a PCM article by Ray Duncan that I
could email you if you like. All 16 bits, though.
--
Simon van Dongen <sg...@xs4all.nl> Rotterdam, The Netherlands
'My doctor says I have a malformed public duty gland and a
natural deficiency in moral fibre,' he muttered to himself,
'and that I am therefore excused from saving Universes.'
Life, the universe and everything
Linux does indeed use mmap() with MAP_ANONYMOUS (which gives you a
zero-filled region.) Using mmap() allows it to munmap() regions --
especially large allocations -- returning the pages to the operating
system, and mremap() (for realloc()) to move pages around by a simple
page-table change.
-hpa
--
<h...@transmeta.com> at work, <h...@zytor.com> in private!
"Unix gives you enough rope to shoot yourself in the foot."