The memory management in DOS is simple, but that simplicity may be deceptive. There are several rather interesting pitfalls that programming documentation often does not mention.
DOS 1.x (1981) had no explicit memory management support. It was designed to run primarily on machines with 64K RAM or less, or not too much more (the original PC could not have more than 64K RAM on the system board, although RAM expansion boards did exist). A COM program could easily access (almost) 64K memory when loaded, and many programs didn’t rely on even having that much. In fact the early PCs often only had 64K or 48K RAM installed. But the times were rapidly changing.
DOS 2.0 was developed to support the IBM PC/XT (introduced in March 1983), which came with 128K RAM standard, and models with 256K appeared soon enough. Even the older PCs could be upgraded with additional RAM, and DOS needed to have some mechanism to deal with that extra memory.
The DOS memory management was probably written sometime around summer 1982, and it meshed with the newly added process management functions (EXEC/EXIT/WAIT)—allocated memory is owned by the current process, and gets freed when that process terminates. Note that some versions of the memory manager source code (ALLOC.ASM) include a comment that says ‘Created: ARR 30 March 1983’. That cannot possibly be true because by the end of March 1983, PC DOS 2.0 was already released, and included the memory management support. The DOS 2.0 memory management functions were already documented in the PC DOS 2.0 manual dated January 1983.
In PC DOS 2.0, three memory management functions were introduced: ALLOC (48h), DEALLOC (49h), and SETBLOCK (4Ah). The DEALLOC function may be better known as “free” and SETBLOCK as “resize”. The all-caps names are used in the actual DOS source code.
Structure
The memory managed by DOS (the “memory arena”) starts out as a single contiguous block. It begins just past the end of statically allocated memory and ends at the end of conventional memory. The available memory can be subdivided into smaller blocks through allocation. After a number of cycles of allocating and freeing memory, the available memory may be split up into a relatively large number of blocks, often a mix of free and used memory.
Each block of memory is prefixed by a header. Note that in the DOS source code, this is called an “arena header”. In third party literature, it is usually called a “memory control block” or MCB. This article will use the MCB terminology.
First of all, DOS manages memory in units of paragraphs (16 bytes), not individual bytes. This approach is derived from the segmented 8086 architecture. Managing memory in paragraph units allows DOS to use 16-bit quantities to record the starting address and size of each block. In addition, the starting paragraph address is also implicitly the segment address of the block. Note that due to tracking sizes in terms of paragraphs, DOS memory blocks are not limited to 64K.
The MCB by necessity takes up an entire paragraph, even though only 5 bytes were initially used; the following is an excerpt from MS-DOS 2.11 DOSSYM.ASM:
... continue reading