How MS-DOS Allocates Memory via INT 21h Function 48h
In MS-DOS 6.22, memory allocation through Interrupt 21h, Function 48h provides dynamic conventional (and optionally upper) memory management by traversing a linked chain of Memory Control Blocks (MCBs). When an application requests a block of memory, the operating system evaluates available memory pools against the requested size in paragraphs, applies the active allocation strategy, updates or splits the corresponding MCB, and returns the segment address of the allocated space or an error code indicating insufficient memory.
Register Interface and Parameters
To invoke the memory allocation function, a program sets the CPU registers as follows:
- AH:
48h(the DOS function dispatcher index) - BX: The number of 16-byte paragraphs requested
Upon return, the CPU Carry Flag (CF) denotes success or failure:
- Success (CF = 0):
AXcontains the initial segment base address of the allocated memory block (the first usable paragraph immediately following its MCB). - Failure (CF = 1):
AXcontains an error code (typically08hfor "Insufficient Memory" or07hfor "Memory Control Blocks Destroyed"), andBXreturns the size in paragraphs of the largest contiguous free block found.
Memory Control Block (MCB) Structure
MS-DOS manages memory as a singly linked list of arenas. Every block of memory is preceded by a 16-byte (one paragraph) header known as an MCB or Arena Header.
An MCB contains the following structure:
- Offset 00h (1 byte): Block type identifier. ASCII
'M'(4Dh) indicates an intermediate block; ASCII'Z'(5Ah) indicates the final block in the chain. - Offset 01h–02h (Word): Owner Process Segment Prefix
(PSP). A value of
0000hindicates that the block is free. Any non-zero value represents the segment address of the program that owns it. - Offset 03h–04h (Word): Size of the memory block immediately following this MCB, measured in 16-byte paragraphs.
- Offset 05h–07h (3 bytes): Reserved by DOS.
- Offset 08h–0Fh (8 bytes): ASCII name of the owning program (introduced in DOS 4.0 and retained in 6.22).
Internal Execution and Traversal
When INT 21h, AH=48h executes, the DOS kernel carries
out the following operational steps:
- Chain Traversal: DOS locates the first MCB via an
internal variable stored in the DOS List of Lists (SysVars). It then
walks through the chain paragraph by paragraph by calculating the
segment address of the next MCB:
Next_MCB_Segment = Current_MCB_Segment + Current_MCB_Size + 1. - Strategy Evaluation: DOS checks the allocation
strategy set for the system (configured via
INT 21h, AX=5801h). The default strategy is First Fit (allocating the first free block that is large enough). Alternative strategies include Best Fit (allocating the block closest in size to minimize fragmentation) and Last Fit (allocating from the highest available address down). - Upper Memory Blocks (UMBs): If the program or
system has enabled UMB linking (via
INT 21h, AX=5803h), DOS will include upper memory arenas (between 640 KB and 1 MB) in this search path according to the active strategy.
Allocation and Block Splitting
Once DOS selects a free block (Owner == 0000h) that
satisfies the requested paragraph count:
- Exact Match: If the free block's size equals the
requested paragraphs, or is larger by less than two paragraphs
(insufficient room to build another MCB and hold data), DOS claims the
entire block. It assigns the caller's PSP segment address to the
Ownerfield of the MCB. - Block Splitting: If the free block is larger than
the requested size plus one paragraph, DOS divides the block:
- The existing MCB retains its position, but its size field is reduced to match the requested paragraph count.
- The
Ownerfield is updated to the calling program’s PSP. - A new MCB is created directly after the newly allocated space at
Segment = Current_MCB_Segment + Requested_Size + 1. - The new MCB inherits the previous MCB's chain byte (
'M'or'Z'), sets its ownOwnerfield to0000h(free), and sets its size to the remaining paragraphs minus one (for its own header). - The original MCB's type byte is forced to
'M'.
Completion
If a valid block is found and configured, DOS clears the Carry Flag
and returns AX = Target_MCB_Segment + 1.
If the end of the chain ('Z') is reached without
fulfilling the request, DOS sets the Carry Flag, records the size of the
largest available unallocated block found during the traversal into
BX, loads error code 08h into AX,
and terminates the call. If any MCB header type byte contains a value
other than 'M' or 'Z', DOS aborts the search,
sets the Carry Flag, and returns error code 07h, indicating
a corrupted memory chain.