Memory in DOS and Windows 3.1

How Bad Do You Want It?



Greenledge  Studios

T  h  i  n  k    hard,  work  soft




    Memory management under DOS and Windows 3.1 is a sometimes finnicky thing to say the least.   We are referring here to the physical memory, actual RAM.   Assuming that you are a die-hard Windows 3.1 user, you are going to love this.   The two key files used by DOS to configure memory for use with DOS and Windows 3.1 are CONFIG.SYS and AUTOEXEC.BAT, and we will simplify their monikers to CONFIG and AUTOEX for the sake of brevity.   You can't, as far as I know, change their filenames.

    CONFIG, the configuration file, is able to do more than AUTOEX in configuring memory.   The statement DEVICE=HIMEM in CONFIG is the means by which extended memory (that's memory above 1 Mb) is made accessible to Windows.   The real crusher, though, is the DEVICE=EMM386 statement.   Both HIMEM and EMM386 must be loaded low, so a DEVICEHIGH= has no advantage for these two drivers.   But still my beating heart if some of the other drivers can't be loaded high, and when they are, more low memory becomes available for DOS programs!   'High' means in the range 640Kb-1Mb, which is only high compared to conventional DOS memory.   DOS programs run in conventional memory (0-640Kb) and require a contiguous block of free space.   Depending on how many drivers you are using, how you use UMB's (that's 'High' memory again, i.e. 640Kb-1Mb) could well determine if that DOS application runs at all, especially in that somewhat less-than-roomy DOS virtual machine that runs under a Windows shell.   Even though EMM386 is an expanded memory manager, and granted that expanded memory is obsolete except in the case of certain equally obsolete software, using EMM386 also allows the inclusion of memory for use as upper memory blocks (UMB's), and adding NOEMS to the command line ensures that no memory will be wasted for unneeded expanded memory.   The order is HIMEM, EMM386, and then a statement that looks like this: dos=high,umb

    That last command line uses memory most efficiently by loading DOS into the HMA, which is just above 1Mb.   This works well because DOS is designed to be loaded there.   It also allows those precious UMB's to be used by DOS.   But believe it or not, first you have to find them.   If you are using a monochrome display adapter (technophobes read 'no colour display'), you can skip the next part.

    The upper memory region B000-B7FF is the monochrome display region for IBM PC compatible systems, and if you are not using it for anything, you can reclaim it by adding i=B000-B7FF to the EMM386 command line.   So far, we have (in CONFIG):

DEVICE=C:\DOS\HIMEM.SYS
DEVICE=C:\DOS\EMM386.EXE NOEMS i=B000-B7FF
dos=high,umb
This works in DOS to allow use of that memory region normally used for monochrome displays, an actual 32K more potential memory!!   But in Windows 3.1 you get an error message unless you get the MONOUMB.386 (MONOUMB2.386 is provided on the Windows disks, but may not work for you) driver from Microsoft, put it in your WINDOWS\SYSTEM directory, and add some lines to the [386Enh] section of your SYSTEM.INI file (in the Windows directory).   Specifically, you need the statements:
device=monoumb.386
DualDisplay=1
If this seems like a bother, it's not when you consider there are programs that will actually run because you did it.   Actually, it's phenomally amazingly great!   But that's not all.   That's not even close to all that you can get with good memory mapping and utilization.   Read on.

    Memory mapping, the documenting of how memory is used, is extremely significant to the fraction of usable memory which is actually utilized, and the reliability with which it can be used.   You may have documentation from your manufacturer which tells you precisely which addresses in the upper memory are used for what, and what is available.   Also, EMM386 often finds some space on its own, and seems to know enough not to use certain areas even if you tell it to.   If there is a conflict, the worst that will happen is that the system will not boot, which means you need either a bootable floppy disk or a multiple-configuration CONFIG file in order to get started.   If your documentation says you should have memory available, and it is already being used, then you may choose to believe the documentation, or you may want to try a few things.   If you are making a memory map from scratch, the same principles apply.   First, find how upper memory is currently being used by typing at the DOS prompt: mem/d/p [Enter].   Pressing [SPACE BAR] until you arrive at the section headed 'Upper Memory Detail', you should make note of the segment addresses on the left, as well as the sizes of the UMB's, and how much is free space available to MS-DOS.   Even long after all your memory is optimized, you will still want to return to this method of viewing the upper memory usage.   If you find there is free space available, it would be tempting at this point to see what drivers are currently loaded in conventional memory, and to just make the simple changes necessary to load them high, but it is far more efficient if you have the discipline to do the memory mapping first.   There are more subtleties that you can learn later, but generally when a program loads high it goes into the largest free block available even if it could fit elsewhere.   This can be important because it means that the order of loading drivers can affect the ability even to load them high at all.   It also means that any recoverable memory (that is memory that can be discovered as usable by trial and error, but which is not yet mapped as available) can have a profound effect on the way in which the final optimization takes place.   So it is crucial that the mapping be done first.   It's easy.   Make sure you have a bootable floppy first (a good idea in any event).   You could try including random memory segments in the range C000 to FFFF (upper memory as described in hexadecimal address format), but it is more efficient and satisfying to have a system of some kind, and it prevents quitting prematurely out of discouragement.   Besides, you almost certainly will find some memory you didn't know you had, and that can be exciting, so you need a system to prevent your doing something stupid in all the excitement (like forgetting where the memory was).   If you want to be really systematic, just use i=C000-C0FF (a 4K block) first, writing down the result-- does it boot?   If not, that's good.   You learned something.   But write it down!   Now reboot using the floppy or any other way you can, and try the next 4K block (i=C100-C1FF).   If this sounds tedious, then you can try to go for the gusto right off the bat.   Using i=C000-FFFF is not likely going to work (stay away from A000-AFFF and B800-B9FF for now), but something like C000-EFFF may surprise you.   Be creative, and remember that it is your computer.   When you have finished finding all the available memory you can in the region C000-EFFF, and I mean every bit of it, then (and only then) should you proceed to map the area between F000 and FFFF, 4K at a time.   Find any?   I'm almost sure you did.   You can monitor the upper memory again any time you want using mem/d/p.   If you didn't find one single 4K block that you could include that wasn't shown by your mem/d/p before, then you may choose to go back and do it all again, especially if you have any doubts.   Now, how do you know if you have more memory?   The simple command: mem [Enter], shows you total memory (under 1Mb), as well as some other things.   The total memory will be bigger if you have uncovered new usable memory.   Make sure you are including all the 4K blocks you found that worked (it all has to be on the EMM386 line in CONFIG, but adjacent 4K blocks can be lumped together like i=C000-EDFF).   Don't be so surprised, I told you you were going to love this.   Secondly, use your mem/d/p and look at the "upper memory" region again.   I hope you were using mem/d/p all the way through.   Now write it all down.   It's a good habit to get into.   Congratulations!   You've just finished mapping your memory.   Exciting to say the least.

    Now the final stage of the journey.   You've come this far, you're not about to give up.   This is going to take some trial and error, but there is a good deal of logic in it too.   In general, when using DEVICEHIGH= in CONFIG you want to load your largest drivers first, although I am well aware that this is not always possible.   You can also use LOADHIGH (equivalent to LH) in AUTOEX or even at the DOS prompt to load some drivers later if you want or need to.   The goal is to have as little free upper memory as possible, and the largest possible contiguous (uninterrupted) block of low memory.   You determine the low memory number by either running very large DOS programs or by using mem to check the largest size of program which it reports as being possible to run.   Check how much DOS memory is available to Windows by running mem at the DOS prompt in Windows.   Okay, you're done, but don't do this any more after this, eh?   You might get to enjoy it too much, and then for the rest of your life you'd have to get used to the fact that you use memory highly efficiently, and your programs run, and we certainly wouldn't want that to happen.   Besides, there are too many other things to learn, and you wouldn't want to spend the rest of your life mapping memory, would you?


Back to Windows 3.1 Page

Back to Main Page