CREEPINGNET'S WORLD
DOS Memory Management
Memory Management in DOS Explained
DOS Memory Management is one of the most, well, confusing things on oldschool PC's to deal with. Most people, including back then, who were not involved in computing, thought to themselves "Hey, isn't it just as simple as storing at 0KB and not filling it up to (how much RAM the computer has)". See, in DOS, it's not really that simple, there's a certain structure to memory.
Hardware Memory Limits per Hardware Generation
The first thing is the restriction of how much RAM your computer can have in hardware, the typical limits. So I have created a table that will explain this in a layman's terms.
ERA MAX RAM DETAILS
PC/XT 640K 640K is the typical maximum for pretty much any IBM Compatible running an i8088-80186 CPU or compatible (NEC V20/V30). This is not 100% true however because some RAM above that can (in the Upper Memory Area) be allocated to things like CGA video cards.
PC AT 16MB The IBM AT's and Clones max out at 16MB RAM addressable, but there's a couple huge catches here. One is that the i80286 started development befor ethe IBM PC came out and really took off, so it has a bit of a problem switching between Protected mode (the mode that allows access up to 16MB of RAM without some kind of memory manager) - a big deal as pure DOS runs in REAL mode (up to 640K accessible without memory managers or some kind of DPMI - Direct Protected Memory Interface - to throw the PC into a Protected Mode State in a way compatible with DOS basically). One way we attempted to manage memory with a 286 computer, was using a LIMS compliant memory manager, like EMM286, or QRAM. Though these days we usually just use HIMEM.SYS.
386 Era 32MB (HW)
4GB Theoretical
The 386 era was the beginning of the 32-bit PC. It introduced several features that helped bring about the popularity of Windows, and of course, helped keep DOS pretty relevant up until about 1997 or so. These included a new DOS Compatible Protected Mode, the ability to use various DPMIs like DOS4GW - allowing for bigger, more complex programs. And you could theoretically push RAM to 4GB, though in actuality, most BIOS and Motherboards (and their respective chipsets) were designed to max out at maybe 16MB (386SX) or 32MB (386DX) in general.
486 Era 128MB (HW)
4GB Theoreticial
Mostly just an expansion and imrprovement on the pre-existing 386, the 486 era saw a major bump in maximum memory capcity, with 64MB being the lower end for most boards, and capacities sometimes as high as 256MB for some really high end 486 workstation and server machines. Same rules apply to the 486 that do to the 386.

DOS Memory Structure
Base Memory - The lower 0KB to 640KB (red) ws what we call "Base Memory" or "Conventional Memory". Basically, the memory area that most programs are loaded into RAM in DOS pre-286. The more of this that is free, the bigger the programs you can get to run - not including it's resource files. The reason this is such a big deal is the less of this there is, the less your DOS System can run. The earliest DOS programs were mere 1-48KB in size, about as small as a Nintendo game, and thusly did not really cause too many problems on 8086/early 286 systems. However, as we reach the late 80's and early 1990's, it was not unusual to find programs that needed as much as 577K to run - such as Ultima 7 or Wing Commander II. The way we fixed this back in the day, was to load certain compatible drivers, TSRs, helper programs, and other stuff into other parts of memory outside the lower 640K memory range to free up more of it to be used byu actual programs. Some better versions of DOS, and replacements for HIMEM.SYS And EMM386.EXE can actually put parts of the DOS KERNEL into other memory areas, and this can allow MORE RAM to be free.

Upper Memory Area - From 640KB (0xA0000) and 1024KB (1MB, 0xFFFFF). 0xC0000 to 0xDFFFF is reserved for legacy SMM and Video BIOS. 0xE0000-0xEFFFF is reserved for BIOS Option ROMs, such as those found on some graphics cards, hard disk controllers, network interface adapters with PXE and other Boot ROMs, and the like. SOMETIMES there are ways to store things in this memory area, such as putting the DOS Kernel here if there's enough room (DOS=UMB), but sometimes it can lead to system instability or just ends up with the memory manager refusing to put the particular items there.

High Memory Area - The HMA was originally a result of the 286 having a 24-bit Memory Address Bus, allowing it to somewhat grab more than 1024K RAM from DOS in some ways. This was used somewhat as a way to not have to "wrap around" to 0KB back on up like an IBM PC/XT type machine would. It used a part of the "Gate A20" line which was a part of the keyboard Controller to be accessed. Later systems such as the 386 and 486 had a more efficient way of pulling this off. This area is controlled by HIMEM.SYS.

EMS Memory - EMS, or Expanded Memory, is memory from about 1024K up to 65535K (64MB), and is allocated using the EMM386.EXE program, or something similar. EMS was used a lot in older vintage games, such as the Sierra On-Line games using the SCI engine and later (they run best with EMS loaded). However, XMS started becoming more popular around the late 386/early 486 era for memory management.

XMS Memory - XMS, or eXtended Memory, is the RAM accessable only to an 80286 or later CPU using HIMEM.SYS. This is the most used form of RAM above 640K, and it requires the CPU to be in Protected Mode to work. This is a big reason for things, such as DOS4GW, and other Direct Protected Memory Interfaces, which allow access to this RAM in an efficient way. Without it, things like DOOM, NESticle, and the original GTA could not have existed on the DOS platform.


DOS Memory & CONFIG.SYS
The typical config.sys file found on a DOS System usually looks like this

DEVICE=C:\DOS\HIMEM.SYS /TESTMEM:OFF
DEVICE=C:\DOS\EMM386.EXE /X D000:DFFF
FILES=40
BUFFERS=45
STACKS=9,256
SHELL=COMMAND.COM /E:1024 /P
DEVICEHIGH=C:\CDROM\CDROM.SYS /D:MSCD001

So up top, let's talk about the memory-based commands. First is HIMEM.SYS - this is the eXtended Memory Driver (XMS). What this does, is it allows a computer (286+) access memory above 1024K per the eXtended Memory Specification. Most later DOS Programs use this and require this to be loaded. This even includes some programs with their own memory manager, such as Ultima 7.

Next down is our EMS memory driver - EMM386.EXE. This driver is used to allow programs that can use Expanded memory to use free Extended memory space. It also can be used as a IRQ hook for some audio devices (WSS), can exclude certain memory areas, and can be used to map memory into unused blocks. The most typical use I've had of this, is with Sierra games running on the SCI engines, as they were designed with a 286 in mind, and designed to make use of this driver to enhance performance. Very often, in programs after 1989, it does not see as much use.

Files=nn - The FILES= line in Config.sys is sometimes required to be a specific value for specific programs. It specifies how many files can be open at once. For example, Borland Turbo C++ needs the value to be 45, while Ultima VII: The Black Gate, needs it to be 40. That said, the lower the number, the more memory saved, and the higher the number required by the program, the more sophisticated the program. 40-45 seems to be around the usual for late era DOS programs. Some programs are more strict about this number than others.

Buffers=nn - The BUFFERS= command determines how many buffers there are to store parts of files to enhance performance in DOS by being able to pull some parts of programs from memory rather than from the disk every bloody time it needs to do something. You can reduce this to open up more memory, but it might be required for some programs, or to gain enough optimization on an old pokey system from the 80's to speed it up enough to be comfy to use.

Stacks=nnThe default value for this is usually 9,256 - which does not mean there are 9,256 actual stacks, but rather, there are 9 stacks of 256 bytes each. There can be as few as 0 stacks to 64, and the size in bytes ranges from 0-512. I will add more on the impact on memory later.

SHELL=Shell is used for a multitude of things including assigning the command interpreter (COMMAND.COM in most cases), setting the environment size (ie /E:1024 in this case). /P is used to determine whether to kick off Autoexec.bat or not (automatically execute file). Shell can be pretty handy at "sawing-in" a few more K's of free BASE DOS RAM.

DEVICE Statements - DEVICE statements are basically used for loading drivers, these can include (but are not limited to): XMS and EMS Memory Drivers, PCMCIA Controller drivers, Network Interface Cards, Mice, Keyboard Expanded Function Drivers, Game Controllers, and the CD-ROM Drive - just to name a few. DEVICE= statements usually load devices into the lower 640K RAM, while DEVICEHIGH= allows a device to be loaded into HIGH memory area. That said, be careful with what you load up high, because some devices don't like to be there!

And the CONFIG.SYS isn't the only thing that determines how much RAM is being used and where in RAM is being occupied - AUTOEXEC.BAT has a piece in this as well....

@echo off
LH C:\AMOUSE\AMOUSE.COM
PATH=C:\DOS;C:\WINDOWS
SET BLASTER=a220, i5, d1, p330, t4
MSCDEX.EXE /D:MSCD001
WIN

This very simple Autoexec.bat file I put above would be like something I'd throw together quickly on a base 486 system with a mouse and CD-ROM without DOS making a file for me. All of these lines use Memory in some say - how much of it - I cannot say for sure. AMOUSE loads first - which is a mouse driver - that's about 2K of RAM, then comes the PATH= environment variable that points to the directories for DOS and Windows - which is why the "WIN" at the end works (which kicks off Windows 3.1x in this scenario). Then there's the SET BLASTER= environment variable - that tells all the software without some form of "auto-detection" where your soundblaster card is, then there's that CD-ROM interface for DOS - MSCDEX.EXE, that's another buncha' "Ks" of RAM being used up.