Extended memory
Extended memory, also known as XMS memory, refers to the random access memory (RAM) located above the first 1 megabyte (1 MB, or 2^20 bytes) of address space in IBM PC-compatible computers equipped with an Intel 80286 or later processor.[1] This memory region became accessible starting with the 80286 microprocessor, which introduced protected mode operation allowing direct addressing beyond the 1 MB limit imposed by earlier real-mode architectures like the 8086/8088 used in the original IBM PC.[2] In the context of MS-DOS and early Windows environments, extended memory was crucial for overcoming the 640 KB conventional memory limit that restricted most applications and the operating system itself.[2] The eXtended Memory Specification (XMS), version 3.0 of which was released in January 1991, provided a standardized API for real-mode DOS programs to allocate, manage, and transfer data to and from extended memory blocks without requiring full protected-mode switching.[1] Jointly developed by Lotus Development Corporation, Intel Corporation, Microsoft Corporation, and AST Research, Inc., XMS enabled efficient use of extended memory on 80286 and 80386 systems, supporting up to 64 MB in version 2.0 and expanding to 4 GB in version 3.0 with MS-DOS 6.0 and later.[3][1][2] A key component of XMS implementation was the Extended Memory Manager (XMM), such as Microsoft's HIMEM.SYS device driver, which loaded into memory during boot to handle XMS requests via interrupt 2Fh and provided access to the High Memory Area (HMA)—a 64 KB region (minus 16 bytes) immediately above 1 MB at addresses FFFF:0010h to FFFF:FFFFh—by enabling the A20 address line.[1][2] MS-DOS 5.0, released in 1991, integrated XMS support to load core components like the kernel, command interpreter (COMMAND.COM), and disk buffers into the HMA, freeing conventional memory for applications; subsequent versions like MS-DOS 6.0 further enhanced this with Upper Memory Block (UMB) management via EMM386.EXE, which emulated expanded memory (EMS) using extended memory.[2] Unlike expanded memory (EMS), which relied on bank-switching hardware to map additional RAM into the upper 384 KB of the first 1 MB for real-mode access, extended memory offered direct, linear addressing in protected mode or through XMS, making it more efficient for larger programs and multitasking environments like OS/2 or Windows 3.x.[1] This distinction was vital during the late 1980s and early 1990s, as extended memory facilitated the running of memory-intensive DOS games, spreadsheets, and utilities that would otherwise exceed conventional limits, paving the way for the transition to 32-bit operating systems.[2] By the mid-1990s, as protected-mode OSes like Windows 95 became prevalent, the need for XMS diminished, though it remained a legacy feature in emulators and retro computing.[2]Background and Context
PC Memory Architecture
The IBM PC-compatible memory architecture, introduced in 1981, was fundamentally shaped by the Intel 8088 microprocessor, which featured a 20-bit external address bus capable of addressing up to 1,048,576 bytes (1 MB) of physical memory. This design utilized real mode addressing, where memory is accessed through a segmented model combining a 16-bit segment register and a 16-bit offset to form a 20-bit physical address via the formula (segment value × 16) + offset. The segmented approach allowed the 8088 to exceed the 64 KB limit of simpler 16-bit addressing schemes while maintaining compatibility with existing software tools and development environments from the era. The 8088's architecture, with its 16-bit internal data path but 8-bit external bus, was selected by IBM to reduce system costs by enabling the use of less expensive support chips and memory interfaces compared to the full 16-bit bus of the related Intel 8086.[4][5][6] The PC's memory map divides this 1 MB address space into distinct segments to balance user-programmable RAM with hardware requirements. Conventional memory occupies addresses 00000h to 9FFFFh (0-640 KB), serving as the primary area for the operating system, applications, and data; this region starts with 16-64 KB on the system board and can expand to 256 KB via add-on cards. Above this lies the upper memory area (UMA) from A0000h to FFFFFh (640 KB-1 MB), reserved for system peripherals and firmware: for instance, video buffers at B0000h-B7FFFh (monochrome, 32 KB) and B8000h-BFFFFh (color/graphics adapter, 32 KB), followed by optional adapter ROMs and the system BIOS ROM at F0000h-FFFFFh (64 KB, including power-on self-test routines and basic I/O services). This allocation imposed a hardware-enforced 1 MB barrier, as the address bus (A0-A19) could not directly access beyond this range without additional mechanisms.[5] To ensure backward compatibility when evolving to later processors like the Intel 80286 in the 1984 IBM PC/AT, the architecture incorporated the A20 address line (bit 20 of the bus), which is disabled by default in real mode to mimic the 8088's wraparound behavior—where addresses exceeding FFFFFh loop back to 00000h—thus enforcing the 1 MB limit and preventing conflicts with legacy software assuming this constraint. Enabling the A20 line, typically via the keyboard controller at I/O ports 60h or 64h, extends addressing by allowing the 21st bit to function, though real-mode software remains confined unless explicitly managed. This design choice stemmed from the 8086/8088 family's origins in the late 1970s, when 1 MB was deemed sufficient for business applications amid high memory costs (around $25 per 64 KB in 1981), prioritizing affordability and interoperability over future scalability.[7][6][8]Distinction from Other Memory Types
Extended memory refers to the physical RAM installed in an IBM PC or compatible system above the first 1 megabyte (1 MB) of address space, which is inaccessible to standard real-mode applications without specialized software or hardware mechanisms to enable access.[9][10] In the context of early PC architecture, this limitation stems from the 20-bit addressing of the Intel 8086 processor, capping the real-mode address space at 1 MB.[9] In contrast to expanded memory, which follows the Lotus/Intel/Microsoft (LIM) Expanded Memory Specification (EMS) and simulates additional address space by mapping pages from a dedicated memory board into a 64 KB page frame within the upper memory area (between 640 KB and 1 MB) via bank switching, extended memory consists of direct physical RAM beyond the 1 MB boundary without such mapping techniques.[11][10] This makes extended memory more straightforward for direct allocation in protected mode but requires mode switches from real mode for DOS compatibility, whereas EMS operates entirely within the 1 MB limit using software-driven paging.[9] In protected-mode operating systems like Windows or OS/2, memory above the 1 MB threshold is directly addressable by the OS kernel using virtual memory and paging mechanisms, enabling larger address spaces and multitasking without the real-mode constraints or XMS/EMS specifications needed for DOS applications. Extended memory, however, specifically pertains to the DOS-era concept of RAM above 1 MB accessed primarily through real-mode extensions or temporary protected-mode excursions, emphasizing compatibility with legacy 16-bit applications.[10][12] Although extended memory can be installed and partially utilized on 80286-based systems, which support up to 16 MB total via protected-mode segments limited to 64 KB each, full utilization—such as larger contiguous blocks up to 4 GB with 4 GB segment sizes—requires an 80386 or later processor due to enhanced descriptor table capabilities and addressing modes.[9][13]History
Development in the 1980s
The development of extended memory emerged in the early 1980s amid the growing constraints of PC memory addressing, particularly with the IBM PC XT released in 1983, which used the Intel 8086 processor and allowed installation of RAM up to 640 KB in conventional memory, while the upper memory area beyond that point remained largely inaccessible to DOS due to hardware reservations for adapters and ROMs.[6] This inherent 1 MB address space barrier in the 8086 architecture highlighted the need for innovative approaches to utilize additional RAM, setting the stage for later advancements.[6] A pivotal shift occurred in 1984 with the introduction of the IBM PC AT, featuring the Intel 80286 processor capable of addressing up to 16 MB of RAM via its 24-bit address bus.[6] Despite this hardware capability, the 80286 operated in real mode for DOS compatibility, confining applications to the 1 MB limit and making the memory above that threshold—termed extended memory—inaccessible without mode switches or other workarounds.[6] This limitation persisted, prompting experimental hardware modifications, such as manually enabling the A20 address line through the keyboard controller to bypass the 1 MB wraparound and experimentally access high memory regions on 80286 systems.[14] In 1985, the Lotus/Intel/Microsoft (LIM) consortium released the initial Expanded Memory Specification (EMS) 3.0, emphasizing bank-switching methods to provide additional memory beyond the 640 KB DOS limit on 8086-based machines.[6] Although EMS targeted expanded memory via add-on cards rather than direct addressing, it indirectly stimulated interest in straightforward access to extended memory on 80286 platforms, as users and developers explored ways to leverage the processor's full potential without complex paging.[6] By 1988, Microsoft introduced HIMEM.SYS, the first device driver specifically designed to manage extended memory on 286 and higher systems, enabling basic allocation and transfer functions in real mode.[15]Adoption and Standardization
The eXtended Memory Specification (XMS) version 2.0 was released on July 19, 1988, by a consortium including Microsoft Corporation, Lotus Development Corporation, Intel Corporation, and AST Research, Inc., establishing a standardized API for accessing extended memory in MS-DOS environments on 80286 and 80386 processors.[3] This specification enabled consistent, machine-independent management of memory above the 1 MB boundary, addressing fragmentation issues in prior ad-hoc implementations and facilitating broader compatibility across PC hardware.[3] Adoption accelerated with Microsoft's inclusion of the HIMEM.SYS device driver in MS-DOS 5.0, released in June 1991, which provided native XMS support and allowed loading of the operating system into the High Memory Area (HMA) via CONFIG.SYS, freeing conventional memory for applications.[16] By 1990, major software like Windows 3.0 incorporated XMS compatibility in its Standard and 386 Enhanced modes, enabling programs to utilize extended memory for tasks exceeding the 640 KB conventional limit and supporting the loading of larger applications on systems with increasing RAM.[17] XMS version 3.0, released in January 1991, further enhanced the standard by introducing 32-bit functions for addressing up to 4 GB of extended memory on 80386 and later processors, aligning with the era's hardware advancements where consumer PCs commonly supported RAM capacities up to 64 MB.[1] However, XMS relevance declined in the mid-1990s as operating systems like Windows 95, released in 1995, shifted to 32-bit protected mode, allowing direct access to much larger address spaces without reliance on DOS-era memory managers.[18]Extended Memory Specification (XMS)
Core Features
The Extended Memory Specification (XMS) serves as a standardized software interface that enables real-mode programs, such as those running under MS-DOS, to allocate, move, and lock blocks of extended memory located above the 1 MB boundary.[19] This interface is implemented through an Extended Memory Manager (XMM) driver, which abstracts the complexities of direct hardware access, allowing applications to utilize extended memory for data storage without entering protected mode.[20] Developed jointly by Lotus, Intel, Microsoft, and AST Research, XMS version 2.0 was standardized in 1988 to provide a consistent method for memory management in IBM PC-compatible systems, supporting up to 64 MB; version 3.0, released in January 1991, extended capabilities to 4 GB via super extended memory.[20][3][1] A central concept in XMS is the allocation of memory blocks in fixed 1 KB units, managed through a handle-based system where each allocation returns a unique handle for subsequent operations.[19] Handles ensure secure and isolated access, preventing direct pointer manipulation that could lead to addressing errors in the real-mode environment. The XMS driver handles the enabling of the A20 address line as needed, which is essential for accessing extended memory by allowing the 21st address bit to be used for linear addressing beyond 1 MB without wrapping.[19] This handling simplifies usage for applications, as manual A20 manipulation—prone to compatibility issues on various hardware—is delegated to the manager, ensuring reliable access to the entire extended memory space without user intervention. Error handling in XMS is managed through standardized return codes issued by the XMM in response to service requests, indicating failures such as insufficient available RAM or hardware conflicts that prevent allocation.[19] These codes, typically returned in a register like BL when the primary operation indicator (AX) is zero, allow applications to gracefully handle exceptions, such as retrying allocations or falling back to conventional memory, thereby enhancing system stability.[20]API and Functions
The Extended Memory Specification (XMS) defines an application programming interface (API) accessed through a control function entry point obtained via interrupt 2Fh. To detect the presence of an XMS driver, software sets AH=43h and AL=00h before issuing INT 2Fh; if AL returns 80h, the driver is installed. To retrieve the entry point address, AH=43h and AL=10h are used with INT 2Fh, returning the far address in ES:BX for subsequent far calls to the XMS manager. Each function call to this entry point uses AH to specify the function number, with returns in AX (0001h for success, 0000h for failure) and BL providing an error code on failure, such as 80h for unimplemented or A0h for insufficient memory.[1][21] Core allocation functions enable management of extended memory blocks in kilobyte-sized units, returning opaque handles for reference. The Allocate function (AH=09h) requests a block of DX kilobytes, returning a handle in DX on success; it fails if no free memory or handles are available. The Free function (AH=0Ah) releases a block specified by DX handle, succeeding only if the block is unlocked and valid. The Reallocate function (AH=0Fh), available in XMS version 2.0 and later, resizes an existing unlocked block to BX kilobytes using DX handle, preserving data if possible but failing on locked blocks or insufficient resources. These functions ensure machine-independent memory management without direct addressing.[1][21] Data transfer between conventional memory (below 1MB), extended memory, or other blocks is handled by the Move function (AH=0Bh), which requires DS:SI pointing to a move structure containing a 32-bit length, source handle and offset, and destination handle and offset. This structure supports copies involving handles FFFFh for conventional memory (with offsets relative to segment 0000h) or valid extended memory handles, enabling efficient bulk data movement without temporary buffers. Query functions provide status: Get Version (AH=00h) returns the XMS version in AX (e.g., 0200h for 2.0 or 0300h for 3.0), internal revision in BX, and HMA availability in DX bit 0; Query Free (AH=08h) reports the largest available block in AX and total free extended memory in DX, both in kilobytes.[1][21] For direct access on 80386 or later processors, blocks can be locked into linear address space. The Lock function (AH=0Ch) takes a DX handle and returns a 32-bit linear address in DX:BX on success, incrementing a lock count; it fails if the lock count exceeds 255 or on hardware limitations. The Unlock function (AH=0Dh) decrements the lock count for the DX handle, requiring prior locks and failing on invalid or zero-count handles. Locked blocks remain fixed in physical memory, avoiding relocation issues during moves or reallocations. XMS version 3.0 introduces the Request HMA function (AH=01h) to allocate the 64KB High Memory Area above 1MB, using DX=FFFFh for applications or a specific byte count for TSRs; success grants exclusive access via conventional addressing with A20 line enabled.[1][21] The following table summarizes the core XMS functions with their parameters and returns for versions 2.0 and 3.0, where applicable:| Function | AH Value | Input Parameters | Return Values | Key Notes |
|---|---|---|---|---|
| Get Version | 00h | None | AX: version (e.g., 0300h); BX: revision; DX: HMA flag | Supports HMA query in all versions. |
| Request HMA | 01h | DX: bytes or FFFFh | AX: 0001h success | Version 3.0 only; enables A20 for HMA. |
| Query Free | 08h | None | AX: largest block (KB); DX: total free (KB) | Reports simulated free space. |
| Allocate | 09h | DX: size (KB) | AX: 0001h/0000h; DX: handle | Minimum 1KB; handles are 16-bit. |
| Free | 0Ah | DX: handle | AX: 0001h/0000h | Must be unlocked; coalesces free space. |
| Move | 0Bh | DS:SI: move structure (source/dest handles, offsets, length) | AX: 0001h/0000h | Handles FFFFh for conventional memory. |
| Lock | 0Ch | DX: handle | AX: 0001h/0000h; DX:BX: linear address | For 386+; max 255 locks per block. |
| Unlock | 0Dh | DX: handle | AX: 0001h/0000h | Decrements lock count. |
| Reallocate | 0Fh | BX: new size (KB); DX: handle | AX: 0001h/0000h | Fails if locked; data preserved if shrinking. |