How do you access more memory (above the 1MB) in DOS if the 640KB of conventional memory are not enough?

I have read a lot about this, but I couldn't figure out how to do this in actual code. Is there an API for this (like HIMEM.SYS), or can I code it myself? Any answer is fine, whether it uses the XMS or the EMS standard or manually written code. From what I read, though, EMS requires specialized hardware, which is not very convenient.

If you can, please also explain if there are any differences between doing it on an Intel 80286 or an Intel 80386. Does it necessarily require switching to protected mode?

  • 4
    The question is way to broad as it stands. There are various extenders and API and they do differ for 286 as well 386 and above, as do the ways to do it without. Answering this thruout would require a whole tour about memory management, which is past what the stack exchange format can do. Please narrow this down to a concrete issue (what you want to do), environment (OS, extenders) and platform (286, 386, ...)
    – Raffzahn
    Mar 21, 2020 at 18:02
  • 2
    @BrianH you are confusing expanded memory (EMS) with extended memory (XMS). 8088/8086 have no XMS, but 286/386 have XMS.
    – Justme
    Mar 21, 2020 at 19:44
  • 3
    @Raffzahn I think it's safe to assume that the OP may not well understand the details of XMS vs. EMS etc. (I certainly can't even remember which is which off-hand.) Rather than declaring the question "too broad" and sending people to other sites for the information they need, just write an answer that gives a high-level overview of what one needs to know about using "more memory than the first megabyte" under DOS. Then we end up with a useful answer instead of just a dead question.
    – cjs
    Mar 22, 2020 at 0:23
  • 3
    @Raffzahn If you think it's better to have the meta-discussion about whether this question is "too broad" or not elsewhere, feel free to delete your comment, start the discussion elsewhere, and I am happy to have the discussion there. (I am merely following your lead here.)
    – cjs
    Mar 22, 2020 at 0:37
  • 2
    @DarkAtom Oh, no problem; just edit the question to explain that more clearly, then! That will encourage alternative answers that you (and others following this question) might find more convenient.
    – cjs
    Mar 22, 2020 at 11:51

3 Answers 3


The eXtended Memory Specification (XMS) 2.0 may be found here and the 3.0 version here. The various function calls are invoked by obtaining the driver's entry point via the muxing interrupt (Int 2Fh). XMS allows for accessing both extended (above the 1MB boundary) and high memory areas.

XMS works much like the original Windows 16-bit memory management: When your program allocates extended memory, XMS returns a handle rather than a pointer to the block. To use the memory, your program calls XMS to lock the handle, which returns a pointer to use. When your program is finished accessing the memory, it should unlock the block, which allows the memory manager to move it in memory without disturbing its contents. You can also move memory blocks between conventional and extended memory without locking the handle.

To answer your other questions: No, there are no differences using XMS on 80286 and 80386 (although as with all things DOS, it's never so simple, such as if your program needs access to the physical pages), and no, your program does not need to switch to Protected Mode to use XMS.

  • 4
    To add to this, the lock/unlock design pattern means that you must forget any pointers to anything in XMS memory when you unlock it. Failing to do so was a common programming problem on 16-bit Windows, and Classic Mac OS, which are quite similar in this respect. 32-bit Windows and Mac OS X both abandoned that idea as far more trouble than it was worth, given a larger address space. Mar 21, 2020 at 20:44
  • 2
    XMS extended memory doesn't have to be locked to use it. Indeed some XMMs do not even allow locking extended memory blocks. The idiomatic way of accessing XMS extended memory is by filling an XMS memory move structure to transfer data between 86-Mode memory and an extended memory block, or between two extended memory blocks. Locking is only useful to a. access memory in protected mode or b. use it for device DMA or such.
    – ecm
    Mar 22, 2020 at 12:09

Before the 286, x86 CPUs can only access 1MiB, so the only way to use memory beyond 1MiB is to use some form of bank switching. The de facto standard for that is Lotus/Intel/Microsoft EMS, which provides access to expanded memory by switching into a “page frame” (typically located in the UMA, between 640KiB and 1MiB). EMS requires hardware on CPUs before the 386, but many 286 chipsets provide support (along with the appropriate driver). On 386 and later, drivers such as EMM386.EXE provide expanded memory. The EMS API is available via interrupt 67h, services 40h to 5Dh. See the full specification for details.

On the 286 and above, the XMS API (implemented for example by HIMEM.SYS) provides access to extended memory, along with UMBs and the HMA. For real mode programs, this is used by copying blocks of memory from conventional to extended and back. The XMS API is accessed through a control function; first use interrupt 2Fh service 4300h to check whether XMS is available, then service 4310h to obtain the control function’s address. See the full specification for details.

286 PCs introduced another API, provided by the BIOS, which is less often encountered in practice: interrupt 15h, service 87h copies memory specified by 24-bit linear addresses (so it can be used to copy conventional to extended and back, but also extended to extended, or conventional to conventional). Memory can be “allocated” by reducing the amount returned by service 88h which indicates the size of extended memory; this is how the VDISK.SYS RAM drive allocates memory for its drives (when extended memory is available).

On the 286 and later, it is also possible to switch to protected mode (using an API such as DPMI, or not) and access extended memory directly, but it’s important to still use APIs to allocate memory. Another approach is to use LOADALL. Many large DOS programs use a DOS extender, which takes care of handling all that for them.

  • 2
    Oh, I remember the days of the AST RAMpage paged RAM card. What a pain in the behind all those workarounds were :) Mar 23, 2020 at 1:56

The HIMEM.SYS is the driver which provides an API that complies with the XMS specification for you to allocate extended memory and move data between conventional memory and extended memory. The XMS specification can be found very easily. Accessing extended memory via XMS driver does not require any protected mode programming from the user and extended memory is used via the API identically regardless of CPU type, it is the XMS driver itself that must work differently on 286 and 386 CPUs.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .