Breaking Through The 1 MB Barrier In DOS With Unreal Mode And More

The memory map of the original 8086 computer with its base and extended memory made the original PC rather straightforward, but also posed countless issues for DOS-based applications as they tried to make use of memory beyond the legacy 1 MB address space. The initial ways to deal with this like EMS, XMS and UMB were rather cumbersome and often impractical, but with the arrival of the 80286 and 80386 processors more options opened up, including protected mode. More interestingly, this led to unreal mode, DOS extenders and the somewhat more obscure LOADALL instruction, as covered by [Julio Merino] in a new article.

This article builds on the first one which covered the older methods and covered the basics of protected mode. Where protected mode is convenient compared to real mode is that with the former the memory accesses go via the MMU and thus allows for access to 16 MB on the 80286 and 4 GB on the 80386. The segment descriptors and resolving of these that make this possible can be (ab)used on the 80286 and up by realizing that these segment descriptors are also used in real mode. Unreal mode is thus about switching to protected mode, loading arbitrary segment descriptors and switching back to real mode. As this is outside the original processor spec, it is commonly called ‘unreal mode’.

Representation of the structure of a DOS-extended application and how it relates to a DOS extender, DOS drivers, and raw hardware access. (Credit: Julio Merino)
Representation of the structure of a DOS-extended application and how it relates to a DOS extender, DOS drivers, and raw hardware access. (Credit: Julio Merino)

In the article [Julio] goes into a lot of detail on this, as well as an assembly implementation of unreal mode, before diving into the fascinating topic of DOS extenders. These are basically the reason why gaming under DOS on the level of Doom and Duke Nukem 3D was a thing at all, with the DOS/4G 32-bit DOS extender (in the form of the Watcom C-compiler DOS/4GW version mostly) forming the backbone. By switching between real and protected mode, applications got the best of both worlds.

The way that this integrated in Windows also gets its own summary, in the form of the DOS Protected Mode Interface (DPMI), which gets around issues with nesting protected modes (until virtualization). Despite the improvements over EMS, XMS and kin, this era of DOS applications came with enough pitfalls (and workarounds) of its own.

17 thoughts on “Breaking Through The 1 MB Barrier In DOS With Unreal Mode And More

    1. Hi, I think PC-MOS/386 also had support for a third-party MMU on 80286-PCs (the OS can run on 8086/80286 PCs, but with limitations). Not sure if it was the same one, though. I’d have to check old reviews, text files on the MOS disks and the manual..

      1. Yes – there definitely was such a card. From memory it plugged into the CPU socket and the 80286 was plugged into it. I can’t remember what it was called but I definitely remember working on an IBM AT running PC/MOS with 4 Wyse PC terminals connected to the serial ports.

    2. Hi again, thank you for the link. I’ve just read it.
      A quote says it could do paging, too.
      I think that’s interesting.

      I suppose that’s more than just a reference to EMS “paging” (bank-switching, EMS Page Frame).

      If so, I wonder if it could have assisted the 80286 in certain “tasks” (pun intended) that the 80286’s own MMU couldn’t or could not very well.

      For example, if it could have assisted with swap-to-disk or could haven been helping to virtualize memory, maybe in tandem with the 80286 MMU.

      (The 80286 MMU can do on its own, has 1GB range, but for some reason it wasn’t well supported. OS/2 1.x supported it; the external MMU could perhaps be used to help to create a two-level virtual memory model, by using parts of the physical memory as some sort of a buffer; I’m just a layman here.)

      Or since the external MMU directly between the 80286 and the motherboard, it technically could intercept i/o ports and re-map or re-direct them to another i/o port.

      That would have been cool for simulation/emulation of certain pieces of hardware. Let’s just think of SoftMPU, which normally requires an 80386 MMU with V86 to work.

      If that external MMU is somewhat capable, it could essentially have helped with software compatibility, not just providing EMS.

      These are just ideas, of course.

      1. There was an EMM286.EXE and HIMEM.SYS (version 2.06 or later) using the 286 CPU’s MMU instead of any hardware bank-switching like most of the EMS cards of the 286’s era. Many years ago my friend wrote an article on the mechanism that is very useful for implementing this, 286’s LOADALL instruction. https://web.archive.org/web/20240116092114/http://www.rcollins.org/articles/loadall/tspec_a3_doc.html
        Where it kind of falls flat on a 286 is the overhead for switching A20 gate on and off slows things around a bit. And EMS memory is gets copied to the lower 1MB instead of there being an ability to ability to do page mapping in V86 mode like you could do on a 386+ machine.
        If you are diligent in managing your calls to DOS/BIOS in your application, you could theoretically use XMS and UMBs of HIMEM.SYS and avoid copying with EMS. Then do a bit of a dance with segment registers that probably no C compiler of the era would appreciate. (I’ve never seen anyone try, but there has to have been someone doing this back in the day).
        I never bothered myself, since during that time I had a rather luxurious 286 with C&T SCAT chipset (82C235). It had a hardware EMS that could from the BIOS settings page pick how much of your system RAM to map to the CPU/XMS and how much to give to the EMS. From there you’d load their EMS device driver (instead of EMMxxx.EXE). You could still have HIMEM.SYS running on your 286 while also having hardware EMS going. The later C&T NEAT chipset for 386 also had this feature, and was present on a lot of budget Baby AT boards.

    1. Something modern like the ATmega328 has 2KB SRAM. A 16-bit CPU with 1 MB of address space and 640kB of RAM seems like an amazing luxury. Plus a large bus that could handle multiple peripherals like serial ports, disk controllers, and even a video card.
      As for 1978. I think if you had a CP/M Z80 with 48KB RAM installed you were living large, even a fraction of that was conceivably workable. Maybe you had even more than 64KB with bank-switching if you have a particularly exotic S-100 system. And then by 1980 people are running some CP/M rip-off with several times the RAM, as much as 640KB? That’s just staggeringly powerful for a single user system.

  1. I did some work on 80286 in-house OS development. The 80286 MMU supported segmented but not paged virtual memory, and the segment size was still limited to 64 kB. So using large data still needed multi-segmenting for a single data item. Pure protected mode for our embedded systems was somewhat usable, but the problem with MSDOS and PC architecture was in getting the CPU back to real mode after shuffling segments in protected mode. (It was done by resetting the CPU, which was time consuming). And continuous loading of the segment descriptors or even segment registers was not very fast either, we are talking many tens of clock cycles per load instruction.

    Anyway, by all means not a bad CPU in its time.

    1. To my understanding, the segment size of the 80286 was limited to 64KB. But not fixed.
      In Protected-Mode, at least, the 80286 could reduce the segment size to a smaller value, which in principle was being a handy feature. That’s in contrast to the 8086/80186, which was fixed to 64KB all the time.

      Windows 3 in 386-Enhanced Mode with virtual memory had used the much smaller 4KB pages, for example.
      The translation happened transparently in background, so that existing Win16 applications with 64KB segments didn’t notice. Unless they had fiddled with the memory directly, like some Windows 1 and 2 applications did. They broke that mechanism, I assume.

  2. Hmm.. Have used BorlandPascal 7 to program ,semi realtime, programs what used MSDOS 6.22 as os where the .exe files has sizes above 2MByte running in DPMI what uses XMS as memory.

    The DOS+BP7 system whould run on 80386SX-33MHz and higher, latest PCs did have a i7-3GHz, and used realmode hardware IRQs which where handled in Protected mode.
    Even starting a new shell (this way the program behaves the same way as the old Terminate Stay Resident but now in MB size iso kB size) with a second big .exe
    Hardware IRQs from 1 mS timer. Serial, Network card, Serial cards (property). PCI cards (also property) and other ISA cards (property) most of the time 5 HWirqs.

    – Serial (property) card for RS485 in multi master mode 375k,9,N,1 format: To, From. Command. DataLen, Data.. , 16bitCRC, Ack/Nack return DataLen: min 0 to 160 max was a HW limit of used DualPorted memory where 0xA0 was the highst free mem Flag setting (so if Full_Flag is Not set a whole msg can be stored, no need to check while sending. Ringbuffers used a same principal for read and write if leftover < 0xA0 then index = index + DataLen + 4 (headerLen) else index = 0
    Up to 15 serial cards using the same IRQ (10) with different IO adresses (0x0120/3, 0x1120/3, 0x2120/3 etc)

    – PCI (property) cards used a PLX 9052 as interface between PCIbus and local (8051 bus or DSP bus)
    – Standard Network card 8Bit/16Bit ISA or PCI running IPX (smaller, simple protocol to make a BP7 integration) where the Data part is used to transport a "serial packet" and Novell Lite for file transport.

    Up to 1998 we used only serial cards later on we used a mix of serial and network cards (e10/e100/e1000)
    – ISA / PCI multi channel RS232 card (MOXA)
    – PC internal RS232 to load camera settings (0..20 cams)

    == PCI cards are "real" Plug aNd Play in DOS while on XPemb / Win7emb are Plug Not (easy) Play ==

    In 2016 when i did retired there where over 2000 machine running world wide with this setup and software.

    1. Yeah, but what does all that mean?

      Between the first and last paragraph, that’s like listening to a fax modem going “brrrthkshshshs” and trying to decipher what the picture looks like.

      1. A complete industrial system, running on DOS, for fruit grading with in paragraph 1 how to overcom the 640 kByte limit. The other paras on what did actual was running.
        For more info about fruit grading equipment have a look at greefa.com

  3. Yeah, but what does that mean?

    Between the first and last paragraph, that’s like listening to a fax modem going “brrrthkshshshs” and trying to decipher what the picture looks like.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.