"Everything That You Wanted To Know About Memory But Forgot To Ask" by Pat Kusbel This section explains how memory is divided and accessed. If you do not need to know about this, but just want to get right into freeing up conventional memory, skip to the next section. WHAT IS UPPER MEMORY, EXTENDED MEMORY, AND EXPANDED MEMORY? Back in the stone ages, Intel came out with their first wonder, the 8086 CPU. It operated in what Intel called Real Mode. Due to the addressing scheme used, a CPU (central processor unit) in the PC (personal computer) operating in Real Mode can only address up to 1MB (megabyte) of memory. Of that 1MB, 384KB (kilobytes) is reserved for hardware in your system. That left 640KB left over for programs to run and thus began the infamous 640KB memory limitation of DOS. Next, Intel came out with the 80286 processor. With it came, a new CPU operating mode called Protected-16 Mode. Protected-16 Mode allows for 24 bit segmented memory addressing or addressability to 16MB. Then came the 32 bit chips in the 386DX and the 486 family of processors. Protected-32 mode allows full 32 bit memory addressing or addressability to 4 gigabytes (GB). The 386's and 486's also introduced another mode of operation called Virtual-86 mode. A processor that supports Virtual-86 mode allows multiple, protected, virtual 8086 machines to be run concurrently each with its own 1MB memory space. Virtual-86 mode is a specially managed variation of Real mode that allows for multiple 1MB 8086 machines to coexist within the 4GB address space. This mode continues to have the 1MB address limitation so I will skip over it as it has no bearing on this topic. So, what does all this mean? DOS runs in a Real Mode environment! When you run a DOS application, you are running in Real Mode with the 640KB limitation. You may ask: "Why don't my programs run in Protected Mode?". Software designers are finally doing just that. As a result, the days of seeing "Not Enough Free Conventional Memory" error messages are hopefully numbered. For now, we must continue to deal with the 640KB DOS limitation. That first 640KB is named "conventional memory". The 384KB of memory that is reserved for system hardware is named the UMA (Upper Memory Area). The UMA is divided into 24 blocks of 16KB each. Anything beyond 1MB is called XMS (extended memory) except for the first 64KB of XMS beginning at 1024KB which is called the HMA (High Memory Area). What about EMS (expanded memory) you ask? Back in the old days of the 286 processor, you added more memory via a plug-in board like a sound card. To access that memory, you needed an Expanded Memory manager such as the EMM386.EXE program. However, the memory installed in 386 and 486 based machines is extended memory, not expanded memory, so EMM386.EXE has the additional job of converting XMS to EMS for programs that need EMS. Adding the RAM parameter to the EMM386 line in the CONFIG.SYS file, e.g., DEVICE=C:\DOS\EMM386.EXE RAM, etc., enables EMS support. When EMM386 sees the RAM switch, it creates a 64KB memory Page Frame in the UMA. Remember, upper memory is addressable by the processor (386 based processors and above) because it is within the 1MB Real Mode addressing boundary. EMM386 uses the Page Frame as a "map" of expanded memory. That is, EMM386 takes memory locations beyond the 1MB boundary and maps them into the Page Frame 64KB at a time (64KB is the size limit of the Page Frame). When a program accesses expanded memory, it's actually accessing the memory within the Page Frame. EMM386 then re-directs the information to the requested memory location. When a program needs to access a different memory location outside the 64KB boundary, EMM386 remaps the Page Frame with the appropriate expanded memory locations. The downside of using EMS memory is that it can only be accessed in 64KB blocks before having to reload new memory locations. This makes accessing expanded memory much slower than accessing extended memory. Why use expanded memory? If software designers wrote programs that used extended memory only, then the people that owned 286's would not be able to use their applications. To maintain compatibility, programs were written to utilize EMS so everybody could use them, even if it meant that the program ran slower. That explains how EMS is accessed, but what about extended memory? Managing extended memory is the job of HIMEM.SYS, the first driver loaded in the CONFIG.SYS file. HIMEM.SYS acts like a traffic cop directing traffic. The traffic in this case is data sent to and from extended memory. When a program sends data to or requests data from extended memory, HIMEM.SYS will switch the processor into Protected mode, take care of addressing the memory and direct the data to the memory location. There is more to it than that, but this is just meant to give you a general idea of what is going on. HOW TO INCREASE CONVENTIONAL MEMORY "All of this is fine and dandy, but how do I go about freeing up memory so I can play my favorite game?" EMM386 performs one other important function. It provides access to the upper memory area. Although most of upper memory is reserved for hardware adapters, etc., there are areas that are free. EMM386 finds these areas and allocates them to be used by system programs, device drivers, e.g., SmartDrive, the mouse driver, sound card drivers, etc. and TSR (Terminate- Stay-Resident) programs. To load a device driver into Upper Memory, the DOS command LOADHIGH or DEVICEHIGH is used. These commands tell EMM386.EXE to load the specified device driver into one of the free areas of upper memory. If a driver cannot be loaded into upper memory, then it is loaded into conventional memory where it competes for space with your programs and games. As more programs are loaded into conventional memory, less space is available to run your favorite application. There are areas of upper memory that can be allocated that EMM386 will not normally use. EMM386 can be forced to use them through the INCLUDE switch: I=xxxx. The INCLUDE switch tells EMM386 that the memory range specified after the 'I' is available in upper memory. We will take a look at a couple of those locations and how we can use them. **** WARNING **** BEFORE MAKING CHANGES TO YOUR CONFIG.SYS OR AUTOEXEC.BAT FILES, COPY THEM TO A SYSTEM DISK (BOOT DISK) AND MODIFY ONLY THE SYSTEM DISK. SYSTEM LOCKUPS AND OTHER BOOT ERRORS CAN AND DO OCCUR. TO RECOVER, YOU HAVE THE ORIGINAL, UNMODIFIED CONFIG.SYS AND AUTOEXEC.BAT FILES ON YOUR HARD DRIVE TO GET YOUR SYSTEM BACK UP AND RUNNING. **** END OF WARNING **** Let's begin with the upper memory region from 'C000-C5FF'. 'C000-C5FF' is a hexadecimal number. Your computer counts in hexadecimal because it's easier to convert from hex to binary (binary is represented by 1's and 0's and is what the computer actually uses to execute programs) than it is to convert from decimal to binary. EMM386 doesn't normally include this region of memory because on some computers it is used by the BIOS. On IBM machines, this memory location is free. We can use it to store drivers by adding I=C000-C5FF to the EMM386.EXE line in the CONFIG.SYS file. This will provide an additional 24KB of upper memory. The next available location in the upper memory area is 'B000-B7FF'. In the days of MONOCHROME monitors, this region was used for the monochrome video buffer. If you use a color monitor, you can use this Upper Memory region to add another 24KB of free Upper memory. If you use this region, you will also need to add the following line to the [386 Enh] section of your Windows SYSTEM.INI file: DEVICE=C:\DOS\MONOUMB.386 One other region of Upper Memory that is available on IBM personal computers is 'E800-EFFF'. Another option is to disable EMS support by adding the NOEMS switch to EMM386 in the CONFIG.SYS file. As you will recall from our earlier discussion on expanded memory, EMM386 takes 64KB of upper memory to create an EMS page frame. If EMS support is disabled, you will be able to use that 64KB for storing drivers. Some programs require EMS, so this may or may not be an option for you. The documentation that came with your software will tell you whether it uses EMS or XMS. Putting it all together, here is what your EMM386 entry in the CONFIG.SYS file should look like using the above information. * No EMS support - maximum free conventional memory * DEVICE=C:\DOS\EMM386.EXE NOEMS HIGHSCAN I=C000-C5FF I=B000-B7FF I=E800-EFFF * EMS support * DEVICE=C:\DOS\EMM386.EXE RAM HIGHSCAN I=C000-C5FF I=B000-B7FF I=E800-EFFF OK, now we have created all of this upper memory, but how do we use it? First, we need to find our device drivers. Device drivers are programs like sound card drivers, the mouse driver, SmartDrive, CD-ROM drivers, etc. These programs can all be loaded into the upper memory area that is now available. To do that, simply add DEVICEHIGH before the appropriate commands in the CONFIG.SYS file and LOADHIGH (or LH) before the commands in the AUTOEXEC.BAT file. EXAMPLE: DEVICEHIGH=C:\{your sound card driver} or LOADHIGH C:\DOS\MOUSE EMM386 will load the drivers into upper memory in the order in which they appear. Drivers specified in the CONFIG.SYS file are processed into upper memory before drivers specified in the AUTOEXEC.BAT file. After you have loaded the drivers high, reboot your computer. At the DOS prompt, type: MEM /C /P This will give you a detailed breakdown of programs that are loaded, their size, whether or not they are loaded into upper memory, and the largest executable program size (free conventional memory). Hopefully, after you have made the changes recommend herein, the amount of conventional memory available to you has increased. Next, enter the following at the DOS prompt: MEM /F This command will show you the amount of free upper memory you now have available for loading device drivers and TSRs. Unfortunately, when programs are loaded into upper memory, they must be loaded into contiguous sections of memory. In other words, a program can not be segmented into different memory locations. Upper memory is divided into REGIONS. In these regions, EMM386 tries to find contiguous, unfragmented blocks of memory to store programs. Now is where the tricky part comes. It may not always be desirable to load a program into upper memory! For example, say that you type the command: MEM /C /P and you see all of your programs loaded high except for SmartDrive which is 34KB in size and is loaded into conventional memory. Yet, the mouse driver, which is 27KB in size, was loaded into upper memory. Furthermore, say that you type: MEM /F and you see that there is 10KB of space left in Region 1 which is where the mouse driver is loaded. In this situation, it would be better to remove the LOADHIGH command from the mouse driver in your AUTOEXEC.BAT and let the mouse load into conventional memory. The reason is that if the mouse is loaded low, there will now be 37KB available in Region 1, which is enough to load SmartDrive, a 34KB program, into upper memory. As a result, you freed up 7KB of space in conventional memory! SmartDrive was taking 34KB, but now the mouse is taking 27KB of conventional memory and SmartDrive is now loaded into upper memory taking up no space in conventional memory. The process of figuring which drivers to load high and which ones to load into conventional memory can be tedious, but it can make a difference between getting an error message of not enough memory and successfully playing your game. There is yet another option to help with the memory crunch. With MS-DOS 6.2 came the ability to write multi-configuration CONFIG.SYS and AUTOEXEC.BAT files. With this option, you can go to a menu at boot up and select the configuration you want to use for that boot session. For example, you have an exciting game to play that runs from your hard drive, yet you don't have enough conventional memory because your CD-ROM drivers are taking up too much space. The solution is to create a configuration that will not load the CD-ROM drivers and then select that configuration at boot up. You won't be able to use your CD-ROM for that session, but you don't care because your game doesn't need the CD-ROM and now you can play it. Then, when you need your CD-ROM, you simply reboot and select the configuration that loads your CD-ROM drivers. I currently have 5 configurations on my system. (1 for windows, 4 for DOS (1 with CD and EMS, one CD and no EMS, one for no CD and EMS, and one for no CD and no EMS.) Using the memory management techniques we talked about above, I am able to get 619KB of conventional memory with SmartDrive, the mouse and CD-ROM drivers loaded! One final note: It is NOT always necessary to load sound-card drivers (these drivers are loaded in your CONFIG.SYS file). By not loading them, you will not be able to control volume levels via software, but you will be able to control volume using the controls on your speakers. Most DOS programs come with sound card drivers included, so yours are not needed. Note that this is NOT true for all DOS applications and all sound cards. If you run across one that does not give you any sound, then you will have to load the drivers. I place a REM in front of my sound drivers in my CONFIG.SYS file. If I run across a program whose sound does not work, I remove the REM and let the drivers load. By REM'ing out sound drivers, you can free up quite a bit of memory (REM means REMARK and tells DOS that the line is a comment line and should not be executed by DOS.) One last thing you can do is to change the STACKS size in your CONFIG.SYS file. If you look in your CONFIG.SYS, you will see a command that says STACKS=x,yyy where x is the number of stacks and y is the size of each stack. A stack is a temporary storage area. When your computer receives a hardware interrupt, such as a request from a program to access the disk drive, it stops what it's doing and stores the data it was processing on the stack along with some other things. When you're running your favorite program, it sets up its own stack. However, sometimes this stack isn't big enough to handle everything and your system crashes. To fix this, Microsoft included the STACKS command. When a non-zero value is included in the STACKS command, programs use the DOS stack instead of their own. The downside of all this is that the DOS stack takes up space in conventional memory. For example, STACKS 9,256 takes up 2,304 bytes (2KB). It may not seem like much, but sometimes 2KB can mean the difference between a program running and not running. Set the STACKS to 0,0 (STACKS=0,0). This will disable the DOS stack and let programs use their own stack. This will not always work for all systems. It all depends on your hardware and the software you're running. STACKS=0,0 will work with most PC's. If, after setting the STACKS to 0,0, you get STACK OVERFLOW errors or your computer locks up, you will have to reset the stacks to what it was before. SUMMARY Freeing up conventional memory can be a tedious, frustrating, and time consuming process. By including areas of upper memory that aren't being used and loading TSRs into them, conventional memory can be freed rather easily. Coupling that with the flexibility of using the multi-configuration option (IBM PC DOS 6.1 or MS-DOS 6.2 and later) and a little experimenting using the techniques we talked about, i.e., setting the STACKS to 0, you can set up your system to run any application with a minimum of trouble. I hope this has helped you to beat the 640KB DOS barrier and taught you a little about what goes on in your computer. The preceding discussion is by no means a concise, detailed explanation of how memory is accessed. The processes I talked about in the first section barely scratched the surface of what is really going on. I left out many details as beyond the scope of this text. This discussion is only intended to give a general idea of how things work and explain how to get around some of the barriers that we encounter as personal computer users.