When a well-behaved program needs additional memory space——for an I/O buffer or an array of intermediate results, for example——it can call Int 21H Function 48H (Allocate Memory Block) with the desired number of paragraphs. If a sufficiently large block of unallocated memory is available, MS-DOS returns the segment address of the base of the assigned area and clears the carry flag (0), indicating that the function was successful.
If no unallocated block of sufficient size is available, MS-DOS sets the carry flag (1), returns an error code in the AX register, and returns the size (in paragraphs) of the largest block available in the BX register (Figure 11-2). In this case, no memory has yet been allocated. The program can use the value returned in the BX register to determine whether it can continue in a "degraded" fashion, with less memory. If it can, it must call Int 21H Function 48H again to allocate the smaller memory block.
When the MS-DOS memory manager is searching the chain of arena headers to satisfy a memory-allocation request, it can use one of the following strategies:
First fit: Use the arena entry at the lowest address that is large enough to satisfy the request.
Best fit: Use the smallest arena entry that will satisfy the request, regardless of its location.
Last fit: Use the arena entry at the highest address that is large enough to satisfy the request.
.
.
.
mov ah,48h ; function 48h = allocate mem block
mov bx,0800h ; 800h paragraphs = 32 KB
int 21h ; transfer to MS-DOS
jc error ; jump if allocation failed
mov buff_seg,ax ; save segment of allocated block
.
.
.
mov es,buff_seg ; ES:DI = address of block
xor di,di
mov cx,08000h ; store 32,768 bytes
mov al,0ffh ; fill buffer with -1s
cld
rep stosb ; now perform fast fill
.
.
.
mov cx,08000h ; length to write, bytes
mov bx,handle ; handle for prev opened file
push ds ; save our data segment
mov ds,buff_seg ; let DS:DX = buffer address
mov dx,0
mov ah,40h ; function 40h = write
int 21h ; transfer to MS-DOS
pop ds ; restore our data segment
jc error ; jump if write failed
.
.
.
mov es,buff_seg ; ES = seg of prev allocated block
mov ah,49h ; function 49h = release mem block
int 21h ; transfer to MS-DOS
jc error ; jump if release failed
.
error: .
.
handle dw 0 ; file handle
buff_seg dw 0 ; segment of allocated block
.
.
.
Figure 11-2. Example of dynamic memory allocation. The program requests a 32 KB memory block from MS-DOS, fills it with -1s, writes it to disk, and then releases it.
If the arena entry selected is larger than the size requested, MS-DOS divides it into two parts: one block of the size requested, which is assigned to the program that called Int 21H Function 48H, and an unowned block containing the remaining memory.
The default MS-DOS allocation strategy is first fit. However, under MS-DOS versions 3.0 and later, an application program can change the strategy with Int 21H Function 58H.
When a program is through with an allocated memory block, it should use Int 21H Function 49H to release the block. If it does not, MS-DOS will automatically release all memory allocations for the program when it terminates.