Windows NT 3.1 (and OS/2) Memory Detection

It is common knowledge that Windows NT 3.1 only recognizes up to 64 MB RAM, unlike NT 3.5 and later versions. This statement can be found in various places, including this blog. The limitation was empirically determined by installing NT 3.1 on various physical or emulated platforms.

It is easy to accept this as a fact since it is well known that even NT 3.1’s minimum requirement of 16 MB RAM was quite high when it was released in 1993, and systems with 64 MB memory (let alone more) were practically unheard of.

Imagine my surprise when I installed the original build 511 of NT 3.1 on a 1995 Intel server board (that’s a whole another story) and saw the full 128 MB RAM being recognized. Clearly “common knowledge” is not the same as actual facts.

Finding official statements on the maximum memory supported by Windows NT 3.1 is difficult. Key information is available from Microsoft in KB117373, but with an important caveat. The KB article talks about INT 15h/E820h usage but does not mention that NT 3.1 does not support that interface. NT 3.5 does and that is in fact why it has no trouble detecting more than 64 MB RAM on typical systems. So what’s the real story with NT 3.1?

The KB article answers that question fairly accurately, although it does not explain the history of the BIOS interfaces. The original IBM PC and PC/XT only supported conventional memory, whose size NT 3.1 queries with INT 12h. The PC/AT introduced the concept of extended memory (i.e. directly addressable memory beyond 1 MB) and added INT 15h/88h service to detect its size. Said function returns the number of kilobytes beyond 1 MB as a 16-bit value. The PC/AT (286) was architecturally limited to 16 MB physical memory which function 88h had no trouble reporting.

Things got complicated with he PS/2 schism. IBM provided separate memory detection interfaces for PS/2 systems. The rest of the world originally stuck with INT 15h/88h to report more than 16 MB RAM.

Once server systems with 64 MB RAM and more started appearing, INT 15h/88h was no longer sufficient. No later than early 1993 (before NT 3.1 was released), some Compaq machines started supporting INT 15h/E801h which separately reports (as 16-bit values) the number of kilobytes between 1 MB and 16 MB, and the number of 64 KB blocks above 16 MB. It is obvious that this function can report up to 4 GB RAM, the 386 (and 486 and Pentium) architectural limit. The same interface was also supported by Phoenix and AMI BIOSes since 1994.

This function has a significant limitation in that the memory it reports must be contiguous. It is possible to have a memory hole (for device addressing) below 16 MB but nowhere else. For that reason, a more advanced INT 15h/E820h function was soon specified. Another rationale for INT 15h/E820h was that with the advent of PCI, operating systems needed to know not just where RAM/ROM/etc. is but also where it isn’t,  and what regions are safe for relocating PCI memory resources into.

The INT 15h/E820h function can report a complex memory map and is supported by modern PCs (it was adopted by ACPI), as well as all modern operating systems. But not by Windows NT 3.1.

NT 3.1

So back to NT 3.1. The OS loader (NTLDR/SETUPLDR) calls INT 12h, INT 15h/88h, and INT 15h/E801h (in that order) to detect the amount of installed memory. Obviously INT 15h/E801h is the key to recognizing more than 64 MB RAM since INT 15h/88h can’t report more.

The catch is that NT 3.1 has to successfully call BIOS INT 15h/E801h and the amount of memory between 1 MB and 16 MB returned in register AX must equal the value previously returned by INT 15h/88h. That requires the amount returned by INT 15h/88h to be limited to 15,360 KB, i.e. 16 MB total. That is exactly the problem because most BIOSes do not limit the amount reported by INT 15h/88h… because if they did, all the software which only relies on that function could not use memory between 16 MB and 64 MB. The limitation is documented in the above mentioned KB article.

Windows NT 3.1 using 1 GB RAM

Windows NT 3.1 using 1 GB RAM

The above screenshot shows NT 3.1 (using the original boot loader) recognizing 1GB RAM when INT 15h/88h returns 15MB and INT 15h/E801h is available.

OS/2 2.11 and Warp

Windows NT 3.1 was not alone in using this logic. OS/2 2.x used a very similar approach, as documented by IBM. OS/2 2.11 used it and the initial OS/2 Warp, as well as Warp Connect, still used the same algorithm. OS/2 Warp Server already changed the logic and works with typical BIOSes. That means an updated OS/2 Warp (or Warp 4) can detect more than 64 MB RAM even when INT 15h/88h reports 64 MB.

OS/2 2.11 recognizing 512 MB RAM

OS/2 2.11 recognizing 512 MB RAM

OS/2 2.0 and 2.1 did not detect more than 16 MB on PC/AT-class machines out of the box, although fixes were available to support larger memory sizes. Needless to say, this was not a huge issue in 1992-1993.


It is worth mentioning that HIMEM.SYS distributed with MS-DOS 6.0 (and likely other HIMEM.SYS versions) can also utilize INT 15h/E801h. Unfortunately, unlike NT 3.1, HIMEM.SYS only calls the function if it determines that the system is a Compaq EISA machine. NT does not implement any such restriction.

Finally, it is unavoidable to mention the infamous “OS select for DRAM > 64MB” option found in many BIOSes, with the choices being “OS/2” and “Non-OS/2”. The option is only useful for OS/2 2.11 and early OS/2 Warp FixPack levels, not for OS/2 in general. On systems with more than 64 MB, it reduces the memory reported via INT 15h/88h to exactly 15 MB, so that the amount of extended memory below 16 MB reported by INT 15h/E801h matches. That satisfies the assumptions of OS/2 2.11/Warp, and presumably NT 3.1, allowing the OS to recognize more than 64 MB RAM. With newer OS/2 and NT versions, the BIOS option is harmful (because it confuses software relying strictly on INT 15h/88h) and should not be used.

This problem is largely a result of lack of leadership. IBM thought it led when it introduced the PS/2 platform, but the rest of the world it did not follow. Compaq, Intel, or Microsoft did not have nearly as much clout in the early 1990s as IBM once did. And so the PC platform turned into a fragmented mess, resulting in many headaches for the users.

This entry was posted in BIOS, NT. Bookmark the permalink.

38 Responses to Windows NT 3.1 (and OS/2) Memory Detection

  1. Yuhong Bao says:

    In this case, the Compaq DeskPro 386 was released before the IBM PS/2 anyway.

  2. Michal Necasek says:

    True, but irrelevant. Did it actually support more than 16 MB RAM?

  3. Yuhong Bao says:

    No, but it did have a 80386 processor with 32 address lines.

  4. Michal Necasek says:

    And that is relevant to BIOS interfaces how exactly?

  5. Richard Wells says:

    Original (1986) Deskpro supported 16MB of RAM but could only install 10 MB (2 on motherboard and 2 expansion cards each with 4 MB).

    Final 386 and 486 Deskpros were rated as being limited to 64 MB of RAM but could have up to 68 MB of RAM installed (2 expansion cards each with 32 MB and 4 MB on motherboard). I don’t know of anyone who tried the maximum memory loadout and reported what happened.

    Compaq SystemPro (1989) was announced as supporting up to 256 MB of RAM. Did break the 64 MB barrier as each memory expansion complex setup could contain up to 96 MB and each CPU card had an additional 4MB. With 2 CPUs and 2 memory expansion setups, that should mean 200MB though everyone seems to list a maximum of 192 MB with two CPU cards. Note that the maximum disk space available was 1.6 GB so full RAM loadouts might prove wasteful.

    Please remember that Compaq pricing in 1990 was about $750 per MB of RAM for the more modest memory expansion cards. I can’t find a price for the 96MB SystemPro assemblage. The base line single 386 SystemPro model with a mere 4 MB cost $16,000.

    Compaq’s SystemPro design was able to keep pace with hardware and OS improvements for 5 years before better techniques were needed to handle larger memory totals. That is about as good as one can expect.

  6. Michal Necasek says:

    The SystemPro is definitely a very historically significant machine (or a family thereof). Would that be the first PC/AT compatible with more than 64MB RAM support? It sounds like it… it would be very interesting to examine the BIOS. Unfortunately getting hold of an old SystemPro ROM dump will probably be very difficult, just like it’s not been possible so far to get a BIOS dump of the original 1986 DeskPro.

    What OS would a customer typically run on a SystemPro loaded with RAM, circa 1990? Some sort of UNIX? NetWare? It wouldn’t be DOS or OS/2 or NT or 386BSD or Linux… Ah, “a custom version of SCO Unix” says Wikipedia, although that refers to the asymmetric multiprocessing and not SystemPro in general.

    It sounds like a SystemPro with more than 64MB RAM would have cost right about $60,000 so not many customers probably needed to worry about more than 64 MB RAM.

    I thought there might be something in the EISA specs but no luck finding the details of the EISA BIOS calls.

  7. Andreas Kohl says:

    It’s an inaccuracy by wikipedia. Please refer to SCO Technical Article 106299 (Feb 1990) that clearly mentions Compaq’s SystemPro supported with MPX 1.0 (other machine there was Zenith Z1000). But it’s true that Compaq and SCO were working together closely for a long time. Of course there was Compaq EFS for SCO UNIX, more a collection of drivers and additional tools.

  8. Yuhong Bao says:

    I think at least later versions of HIMEM uses the EISA BIOS calls to detect the memory.

  9. Yuhong Bao says:

    It would be interesting to see when Compaq SystemPro BIOS introduced the E801 call.

  10. Richard Wells says:

    Some information about OSes planned for use in the early dual processor 386/486 systems can be found in the May 29, 1990 issue of PC Magazine which covers Compaq SystemPro and the Mitac and Netframe competitors.

    SCO Unix, Netware 386, Banyan Vines and LAN Manager all had dual processor variants though with a lot of restrictions. Netware 386 did not support both processors on the Compaq but did on the Netframe. LAN Manager used both processors on the Compaq; however, the second processor was dedicated to handling HPFS. All the OSes were customized specifically for the hardware so even if by some miracle you find a copy it likely won’t work on any other hardware or virtual machine.

    I think Compaq released material on the SystemPro extensions at the time. I can’t locate a copy online and I don’t have a paper copy.

  11. Yuhong Bao says:

    I wonder when NT added support for the extended MP configuration table in MPS 1.4.

  12. dosfan says:

    I don’t recall any EISA functions to return memory size. The INT 15h memory functions are 88h, C7h (PS/2 only), E801h and E820h. EISA functions are INT 15h/D8xxh and are documented in Ralf Brown’s Interrupt List.

    A 386 or 486 with 68MB RAM ?? Even if you could put that much RAM in the system there would be no way to see anything beyond 64MB since INT 15h/E801h didn’t exist at the time. I’m pretty sure that no 386 or 486 BIOS ever supported it (and certainly not the later INT 15h/E820h get system memory map function).

  13. Yuhong Bao says:

    @dosfan: It was in the HIMEM.SYS code.

  14. dosfan says:

    Unless it was reading memory info from an EISA memory card there is no specific EISA get memory size function. The EISA BIOS functions simply deal with EISA cards much like the later PCI INT 1Ah/B1xxh functions do for PCI cards.

  15. Yuhong Bao says:

    @dosfan: Yes, this is exactly what I am referring to.

  16. Richard Wells says:

    The BIOS may only report 64MB but all these systems had methods to access the memory that did not involve the BIOS. Sometimes, this got weird. Corollary recommended that the EISA configuration be set to show 15 MB in BIOS in order for a C-Bus system to realize that more than 64 MB was installed.

    I suspect figuring out the exact technique would require disassembling either the proper HAL or SCO EFS.

  17. Michal Necasek says:

    That occurred to me too. An OS with specific SystemPro support could query the hardware. It could use the EISA card information, or it could probe the RAM, or use some custom hardware interfaces that aren’t publicly documented. Disassembling would indeed do the trick.

    As for NT 3.1, it used INT 15h/88h and INT 15h/E801h as the article states. That means INT 15h/E801h was around in 1993 already (I should probably disassemble the older NT loaders, too!). NT 3.5 (1994) added INT 15h/E820h support. I take it to mean INT 15h/E820h wasn’t around in 1993, or extremely rare.

    There was also INT 15h/DA88h (AMI BIOS only?), often supported by Intel boards.

  18. Chris M. says:

    Later versions of HIMEM do support over 64MB of RAM, they were included with Windows 9x.

    Dell machines of the mid 00s included a curious “OS Install Mode” that limited RAM to 256MB for some unknown operating system that had memory issues, anyone know why they had this option, perhaps Windows 9x (see below)? It appears to only modify the e820 tables. All the Dell machines with the memory limiting option that I have seen were much newer then the Win9x era though.

    On that note, is there anyway to modify the e820 table after boot up? It would be handy to install Windows 9x on high memory machines (anything over 512MB is dicey with that OS) that are otherwise supported by the OS.

  19. Michal Necasek says:

    This is a misconception. The HIMEM.SYS shipped with MS-DOS 6.0 (version 3.09, march ’92) already supports more than 64MB via INT 15h/E801h… but only on Compaq non-EISA machines(!!). SystemPro? I haven’t hunted down the exact revision when this was introduced but I’m guessing 1991-ish.

    There’s generally no way to modify the e820 table. It’s typically in a write-protected ROM shadow. You’d need a TSR that intercepts the INT 15h vector and returns a different/modified table. Which is obviously tricky for situations when you’re booting off of installation media…

    The other option would be modifying the BIOS and re-flashing. But then you’re stuck with that change, and it’s potentially a lot of work.

  20. dosfan says:

    That sounds right. Later versions of HIMEM.SYS (at least PC DOS versions, not sure about MS-DOS versions) also support >64MB on newer PS/2 systems via INT 15h/C7h. Not surprisingly IBM didn’t care about EISA systems.

    Note you should be able to patch HIMEM.SYS to always issue INT 15h/E801h by removing the two lines before the E801h function call (should be a call to a routine which checks if the PC is a Compaq and a conditional jump).

  21. Michal Necasek says:

    Looking up the specs I see that XMS 3.0 (January 1991) has a mechanism to report up to 4GB free memory. However, as we discussed elsewhere, the problem back then was detecting memory above 64MB. On typical systems, old HIMEM.SYS versions won’t find more than 64MB even though they could manage larger memory sizes.

  22. Michal Necasek says:

    Bingo. HIMEM.SYS 3.07 (Feb ’92, shipped with Windows 3.1) uses EISA BIOS INT 15h/D800h and INT 15h/D801h to look for memory that might not be reported by INT 15h/88h. That HIMEM.SYS version does not appear to use any other interrupts to query the memory size. HIMEM.SYS 3.09 (MS-DOS 6.0, Feb ’93) uses INT 15h/E801h but only on Compaq non-EISA systems.

    I take it to meant that the old SystemPro machines had no architected way to report installed memory. Sometime in 1992 or perhaps early 1993, Compaq added INT 15h/E801h. But since early 1992 or maybe 1991, HIMEM.SYS could detect EISA memory and use more than 64MB of it.

  23. dosfan says:

    Looking at the code it seems that HIMEM.SYS uses INT 15h/E801h only on Compaq non-EISA machines.

    P.S. Do a Google search for “IsEISAMachine”

  24. Chris M. says:

    I have several pre-PCI 486 machines here that support over 64MB of RAM, so they aren’t exactly uncommon. Two of the boards, both of which are EISA/VLB, support 256MB! They all use the 06/06/1992 AMI HiFlex core with BIOS dated 1993. I’m guessing they use INT 15h/E801h. Windows 2000 and 98SE have no problems detecting >64MB.

  25. dosfan says:

    If you can boot real DOS on one of those systems then run DEBUG and enter the following:

    mov ax,e801
    int 15

    p 2

    If the INT 15h/E801h is supported then the carry flag will be clear and AX will contain the amount of extended memory below 16M in kilobytes (usually 3C00h if > 16MB RAM) and BX will contain the amount of extended memory above 16MB in 64KB blocks. Note you have to do this from DOS as Windows will intercept the call and report a function not supported error.

  26. Yuhong Bao says:

    Yes, it is probably E801h. You should boot without HIMEM.SYS loaded before doing the above.

  27. Michal Necasek says:

    EISA was never ever common. What kind of memory modules do these machines take?

    Would be interesting to know if these machines support INT 15h/DA88h which RBIL claims to be part of “AMI PCI BIOS” but could perhaps be older.

  28. dosfan says:

    Is it known when INT 15h/E801h was first used ? Presumably Compaq was the first to implement it and it was copied by the other BIOS manufacturers.

    INT 15h/C7h was used by PC DOS 5.02 and later versions of HIMEM.SYS.

    Note INT 15h/E801h also returns values in CX and DX which would be unaffected by whether HIMEM.SYS was loaded or not:
    AX=extended memory below 16M in kilobytes
    BX=extended memory above 16MB in 64KB blocks
    CX=configured extended memory below 16M in kilobytes
    DX=configured extended memory above 16MB in 64KB blocks

    I have never seen any BIOS return CX and DX values different from the AX and BX values.

  29. Michal Necasek says:

    I couldn’t find INT 15h/E801h used in HIMEM.SYS 3.07 but it was in 3.09. So I’m guessing it showed up sometime in 1992. Since HIMEM.SYS 3.09 only calls it on Compaq machines, I think it’s a fair bet Compaq had it first. Within a few years it was in generic AMI/Award/Phoenix BIOSes.

    I could never figure out a meaningful difference between AX/BX and CX/DX. As you say, everyone seems to return identical values there.

    HIMEM.SYS 3.08 anyone?

  30. dosfan says:

    The AMI specific INT 15h/DA88h seems to have been dropped in later AMI BIOSes. It isn’t supported on the system I have which has an AMI BIOS from 2006. Phoenix BIOSes also support INT 15h/8Ah.

    Finding a specific version of HIMEM could be tough. HIMEM (and EMM386) were distributed with various software (DOS, Windows, MASM, C) and I wouldn’t be surprised if some versions never made it outside of Microsoft. Adding to this is the fact that IBM tended to not change the version number when they made changes (i.e. IBM HIMEM 3.09 is not exactly the same as MS HIMEM 3.09)

    Here is a list of the versions included with DOS:
    HIMEM 2.77 MS-DOS 5.00 / PC DOS 5.00
    HIMEM 2.78 MS-DOS 5.0A / PC DOS 5.02
    HIMEM 3.09 MS-DOS 6.00 / PC DOS 6.10 / PC DOS 6.30
    HIMEM 3.10 MS-DOS 6.20 / MS-DOS 6.21 / MS-DOS 6.22
    HIMEM 3.15 PC DOS 7.00

  31. Chris M. says:

    @Michal Necasek
    The EISA boards take up to 16x16MB 30-pin SIMMs. There were a ton of generic clone VLB boards from the period that took 8x16MB 30-pin SIMMs, so they had to have some way of detecting RAM above 64MB.

    One notable board that I have is a 1993 Micronics EISA2-VL. It can only take 64MB max (likely due to the 88h limit) and has an ancient Phoenix BIOS core from 1988. You can’t enable ROM shadowing if you have over 16MB RAM installed. Why? Because it makes the RAM space dis-contiguous. Instead of mapping the shadowed ROMs on top of the 4GB address space like every other board, Micronics decided to just add 1000000h to the ROM space and shadow it there. Worked great on machines limited to 16MB/24-bit RAM addressing (386SX), not so much on a semi-modern 486!

  32. Michal Necasek says:

    Interestingly, I have a circa 1999 AMI BIOS which doesn’t support INT 15h/E801h either, only INT 15h/E820h and the old INT 15h/88h (box has 1GB RAM, it’s a dual Slot 1 board).

  33. dosfan says:

    That is interesting. I didn’t think there were any BIOSes that supported INT 15h/E820h but not 15h/E801h since E801h came first.

    Do you have a Phoenix BIOS to check ? Based upon the PhoenixBIOS 4.0 User’s Manual their BIOS circa 2000 should support INT 15h functions 88h, 8Ah, E801h and E820h. INT 15h/8Ah is documented to return the amount of extended memory above 64MB in kilobytes in DX:AX.

  34. Yuhong Bao says:

    As a side note, I wonder where INT 15h/E881h comes from and how it was supposed to be called.

  35. dosfan says:

    Is it known who originally defined INT 15h/E820h ? Was it Compaq ? Presumably it was defined around 1994 and was adopted as part of the ACPI 1.0 spec in 1996. Also it seems likely that Compaq defined INT 15h/E801h around 1993.

  36. Michal Necasek says:

    RBIL claims that INT 15h/E820h was “originally introduced with the Phoenix BIOS v4.0” but I’d take that with a grain of salt. I think somehow or other it must have been introduced on PCI systems because EISA already provided a different way of reporting memory regions past 64MB. The other thing is that INT 15/E820h handles memory that’s broken up into several disjoint regions which could be important with various memory holes.

  37. dosfan says:

    When did Phoenix BIOS 4.0 first appear ? I guess it’s safe to say that it was either Phoenix or Compaq who introduced the INT 15h/E8xxh functions and based upon your study of NT 3.1 and 3.5, E801h appeared in 1993 and E820h appeared in 1994. I guess they replaced the vendor specific functions INT 15h/8Ah (Phoenix) and INT 15h/DA88h (AMI) which were likely little used.

    Do you know if IBM systems which supported INT 15h/C7h also supported E801h and/or E820h (I’m guessing not but anything is possible).

    Did any BIOS actually support the 32-bit E881h function ? Presumably it was meant to be called from 32-bit protected mode but that almost certainly wouldn’t be via INT 15h. Was there a BIOS32 ID for it or was the function defined but never actually implemented in favor of E820h ?

Leave a Reply

Your email address will not be published. Required fields are marked *