Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 49 additions & 32 deletions public/catalog.json

Large diffs are not rendered by default.

74 changes: 34 additions & 40 deletions public/programs/ms-dos/alloc.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,90 +9,84 @@ year: 1981
author: "Tim Paterson / Microsoft"
slug: "alloc"
order: 16
description: "Memory management routines in MS-DOS v2.0, showcasing early techniques for handling dynamic memory allocation in constrained environments."
description: "Memory management routines in MS-DOS v2.0, showcasing early techniques for dynamic allocation under tight constraints."

summary:
- point: "Introduced memory arenas for dynamic allocation"
- point: "Introduces memory arena management for dynamic allocation"
link: "https://en.wikipedia.org/wiki/MS-DOS"
link_label: "MS-DOS"
- point: "Adopted Unix-inspired memory management concepts"
link: "https://en.wikipedia.org/wiki/Unix"
link_label: "Unix"
- point: "Optimized for 8086 hardware constraints"
link: "https://en.wikipedia.org/wiki/Intel_8086"
link_label: "Intel 8086"
- point: "Set groundwork for memory management in later DOS versions"
link: "https://en.wikipedia.org/wiki/MS-DOS"
link_label: "MS-DOS"
- point: "Used by hundreds of OEMs in the early PC era"
- point: "Inspired by Unix/XENIX memory management concepts"
link: "https://en.wikipedia.org/wiki/Xenix"
link_label: "XENIX"
- point: "Efficient use of limited hardware resources on IBM PC"
link: "https://en.wikipedia.org/wiki/IBM_PC"
link_label: "IBM PC"

enhancements:
- id: "include-dosseg-and-dossym"
line_start: 1
line_end: 33
title: "The Headers That Defined MS-DOS Memory"
wikipedia_url: "https://en.wikipedia.org/wiki/MS-DOS"
line_end: 85
title: "Why Include Files Were Crucial in Assembly"
wikipedia_url: "https://en.wikipedia.org/wiki/Assembly_language"
image_url: ""
image_caption: ""
content: "These lines include critical assembly headers (`DOSSEG.ASM`, `DOSSYM.ASM`, and `DEVSYM.ASM`) that define the memory management structures and symbols used throughout the file. At the time, MS-DOS was transitioning from a simple single-tasking OS to a more Unix-inspired system with features like subdirectories and device drivers. These headers provided the foundational definitions for memory arenas, process data blocks, and allocation methods. Tim Paterson and Microsoft engineers used these headers to ensure consistency and modularity across the codebase. By abstracting hardware-specific details into headers, they made the code easier to adapt for different OEMs, a key factor in MS-DOS's widespread adoption. This modular approach influenced later operating systems, including Windows and Linux, where header files and modularity became standard practice."
content: "The INCLUDE directives at the start of this file bring in DOSSEG.ASM and DOSSYM.ASM, which define segment structures and symbolic constants used throughout the program. This modular approach allowed developers to reuse common definitions across multiple source files, reducing errors and ensuring consistency. In the early 1980s, this was a practical necessity for managing large assembly projects like MS-DOS, where every byte of memory mattered. Tim Paterson and the Microsoft team leveraged these include files to streamline development and maintain compatibility across different hardware configurations. This modularity influenced later programming practices, including the use of header files in C and other high-level languages."
- id: "arena-free-process-loop"
line_start: 89
line_end: 101
title: "Freeing Memory Blocks by Process ID"
line_end: 189
title: "How MS-DOS Freed Memory Blocks by Process"
wikipedia_url: "https://en.wikipedia.org/wiki/MS-DOS"
image_url: ""
image_caption: ""
content: "This subroutine loops through memory blocks in the arena and frees all blocks allocated to a specific process ID (PID). The programmer's immediate goal was to ensure that memory allocated to terminated processes could be reclaimed efficiently. The use of `arena_signature` and `arena_owner` fields reflects the structured memory management approach inspired by Unix. In 1983, memory management was constrained by the 8086 processor's segmented architecture, which limited addressable memory to 1MB. Efficient reclamation of memory was critical to keep the system running smoothly. This technique influenced future memory management strategies, including garbage collection in higher-level languages like Java and Python. The concept of associating memory blocks with process IDs laid the groundwork for modern operating systems' process isolation and memory protection mechanisms."
content: "This loop iterates through memory blocks in the arena and frees those owned by a specific process ID (PID). The logic checks each block's owner and sets it to a 'free' state if it matches the given PID. At the time, memory management was a critical challenge due to the limited RAM available in early PCs. The IBM PC launched with just 16KB to 64KB of RAM, making efficient memory reuse essential. This routine reflects the influence of Unix-like systems, where processes could allocate and release memory dynamically. The concept of freeing memory by PID laid the groundwork for modern garbage collection techniques and memory management systems in operating systems like Windows and Linux."
- id: "check-signature"
line_start: 193
line_end: 197
title: "Validating Memory Block Integrity"
wikipedia_url: "https://en.wikipedia.org/wiki/MS-DOS"
line_end: 199
title: "The Signature Check That Prevented Memory Corruption"
wikipedia_url: "https://en.wikipedia.org/wiki/Memory_management"
image_url: ""
image_caption: ""
content: "This subroutine checks the integrity of a memory block by validating its signature. The `arena_signature` field ensures that the block is either normal or marked as the end of the arena. If the signature is invalid, the carry flag is set to indicate an error. Memory corruption was a common issue in early computing due to hardware glitches or software bugs. By implementing signature checks, MS-DOS introduced a rudimentary form of memory protection. This approach was inspired by similar techniques in Unix and other operating systems of the era. The concept of using signatures to validate memory blocks influenced later systems, including modern file systems and databases, which use checksums and other integrity checks to prevent corruption."
content: "This subroutine verifies the integrity of memory blocks by checking their signatures. Each block has a predefined signature that indicates its state (normal, end, or invalid). If the signature is incorrect, the carry flag is set, signaling an error. Memory corruption was a common issue in early systems due to hardware limitations and the lack of robust error-checking mechanisms. By implementing signature checks, MS-DOS reduced the risk of crashes caused by invalid memory access. This technique influenced later systems, where metadata and checksums became standard for ensuring data integrity in memory management."
- id: "coalesce"
line_start: 231
line_end: 247
title: "Combining Adjacent Free Memory Blocks"
wikipedia_url: "https://en.wikipedia.org/wiki/MS-DOS"
line_end: 249
title: "Combining Free Memory Blocks for Efficiency"
wikipedia_url: "https://en.wikipedia.org/wiki/Memory_management"
image_url: ""
image_caption: ""
content: "The `Coalesce` subroutine combines adjacent free memory blocks into a single larger block. This technique minimizes fragmentation and maximizes usable memory, a critical concern in the constrained environment of the 8086 processor. The subroutine iterates through the arena, checking ownership and size fields to determine whether blocks can be merged. Fragmentation was a major challenge in early operating systems, as memory allocation and deallocation patterns could quickly lead to unusable gaps. Coalescing free blocks was a direct response to this problem, inspired by similar strategies in Unix. This technique became a standard feature in memory allocators, influencing designs like the buddy system and slab allocation used in modern kernels."
content: "The Coalesce routine merges adjacent free memory blocks into a single larger block. This prevents fragmentation, which could lead to inefficient memory usage and allocation failures. Fragmentation was a significant problem in early PCs, where memory was scarce and allocation patterns were unpredictable. Inspired by Unix-like systems, this approach ensured that MS-DOS could make the most of the limited RAM available. The concept of coalescing free blocks became a standard practice in memory management, influencing algorithms in modern operating systems and programming languages like Java and Python."
- id: "alloc-scan"
line_start: 319
line_end: 327
title: "Scanning for Free Memory Blocks"
wikipedia_url: "https://en.wikipedia.org/wiki/MS-DOS"
title: "Scanning Memory for the Perfect Fit"
wikipedia_url: "https://en.wikipedia.org/wiki/Memory_management"
image_url: ""
image_caption: ""
content: "The `alloc_scan` subroutine iterates through the memory arena to find free blocks that match the requested size. It uses the `arena_owner` field to identify free blocks and checks their size against the requested size (`BX`). This subroutine is part of the `$ALLOC` routine, which handles dynamic memory allocation. At the time, dynamic memory allocation was a relatively new concept, and MS-DOS's implementation was heavily influenced by Unix's malloc function. The ability to scan and allocate memory dynamically was a key feature that enabled more complex applications to run on MS-DOS. This approach influenced later memory allocation strategies, including the heap management systems used in modern programming languages like C++ and Java."
content: "The alloc_scan routine searches through the memory arena for a free block that matches the requested size. It prioritizes blocks based on allocation methods (first, best, or last fit). This technique reflects the influence of Unix memory allocation strategies, adapted for the constraints of the IBM PC. By implementing multiple allocation strategies, MS-DOS provided flexibility for different use cases, balancing speed and efficiency. The concept of scanning for free memory blocks influenced later memory allocators, including malloc in C and dynamic memory management in modern operating systems."
- id: "alloc-do-split-high"
line_start: 441
line_end: 467
title: "Splitting Memory Blocks for Allocation"
wikipedia_url: "https://en.wikipedia.org/wiki/MS-DOS"
title: "Splitting Memory Blocks to Maximize Usability"
wikipedia_url: "https://en.wikipedia.org/wiki/Memory_management"
image_url: ""
image_caption: ""
content: "The `alloc_do_split_high` subroutine splits a memory block into two parts: one for the requested allocation and one for the remaining free space. This technique ensures efficient use of memory by avoiding over-allocation. The subroutine adjusts the size and signature fields of the split blocks to maintain arena integrity. Splitting blocks was a common technique in early memory management systems, inspired by Unix's malloc function. It allowed MS-DOS to handle dynamic memory allocation efficiently despite the limited resources of the 8086 processor. This approach influenced later memory management systems, including the buddy system and slab allocation used in modern operating systems."
content: "This routine splits a memory block into two parts: one for the requested size and another for the remaining free space. It ensures that memory is allocated efficiently, minimizing wasted space. Splitting blocks was a common technique in early memory management systems, where every byte counted. The logic here reflects the influence of Unix-like systems, which used similar strategies to optimize memory allocation. This approach became a foundational concept in memory management, influencing algorithms in modern operating systems and programming languages."
- id: "setblock-grab"
line_start: 605
line_end: 623
title: "Resizing Allocated Memory Blocks"
wikipedia_url: "https://en.wikipedia.org/wiki/MS-DOS"
title: "Resizing Memory Blocks Without Breaking Everything"
wikipedia_url: "https://en.wikipedia.org/wiki/Memory_management"
image_url: ""
image_caption: ""
content: "The `setblock_grab` subroutine attempts to resize an allocated memory block to match a new requested size (`BX`). It uses the `coalesce` subroutine to merge adjacent free blocks if possible, ensuring that the resized block fits within the available memory. Resizing memory blocks was a challenging problem in early operating systems due to fragmentation and limited resources. MS-DOS's implementation was inspired by Unix's realloc function, which allowed dynamic resizing of memory allocations. This feature enabled more flexible memory management, paving the way for applications that required variable-sized data structures. The concept of resizing memory blocks influenced later systems, including dynamic memory allocators in modern programming languages like C++ and Python."
content: "The setblock_grab routine attempts to resize an allocated memory block to a new size specified by the caller. If the block cannot be resized, it returns an error. Resizing memory blocks was a challenging task in early systems due to fragmentation and limited resources. This routine reflects the influence of Unix-like systems, which introduced dynamic memory management concepts that MS-DOS adapted for the IBM PC. The ability to resize memory blocks dynamically became a standard feature in modern programming languages and operating systems, influencing functions like realloc in C."
- id: "dealloc"
line_start: 671
line_end: 675
title: "Freeing Allocated Memory Blocks"
wikipedia_url: "https://en.wikipedia.org/wiki/MS-DOS"
title: "Freeing Memory: The Heart of Dynamic Allocation"
wikipedia_url: "https://en.wikipedia.org/wiki/Memory_management"
image_url: ""
image_caption: ""
content: "The `$DEALLOC` subroutine frees a previously allocated memory block by resetting its `arena_owner` field to the `arena_signature` value. This marks the block as free and available for future allocations. The subroutine also validates the block's signature to ensure integrity before deallocating it. Memory deallocation was a critical feature in early operating systems, as it allowed efficient reuse of limited resources. MS-DOS's approach was inspired by Unix's free function, which provided similar functionality. The ability to deallocate memory dynamically influenced later systems, including garbage collection mechanisms in higher-level languages like Java and C#. This subroutine exemplifies the structured memory management techniques that became standard practice in operating system design."
content: "The $DEALLOC routine frees a previously allocated memory block, marking it as available for future allocations. It verifies the block's integrity before releasing it, preventing memory corruption. Dynamic memory allocation and deallocation were critical for early PCs, where applications needed to manage memory efficiently. This routine reflects the influence of Unix-like systems, which popularized the concept of dynamic memory management. The ability to free memory dynamically became a cornerstone of modern programming, influencing garbage collection algorithms and memory management techniques in languages like Java, Python, and C++."

---

Expand Down Expand Up @@ -838,4 +832,4 @@ CODE ENDS
END


```
```
Loading
Loading