Multiple Code Segments

The medium model doesn't make sense for a small program, and it comes into play only when you have more than one source code module. But then it starts making a lot of sense. In the medium model, each source code module becomes a different code segment. Each of these code segments can be moveable and discardable. The amount of space required to fit your code into memory is the size of the largest code segment.

For instance, the approximately 160 KB of code in Windows WRITE is distributed among 78 separate moveable and discardable code segments. The largest code segment in WRITE is about 8 KB. Thus, when memory is limited, WRITE can continue to run with only an 8-KB code space. As program logic within WRITE moves from segment to segment, the code segment currently in memory can be discarded and a new one can be loaded in.

If you like, you can think of the medium model as a simplified overlay manager: You split your program into multiple source code modules and compile for the medium model. Windows does the rest. In order to work efficiently, the medium-model approach requires some planning. The functions in each of your source modules should be organized in functional groups. When your program is dealing with such routine matters as processing mouse messages, for example, it should not have to load several code segments to get from the top of the window procedure to the bottom.

While using the medium model is certainly the easiest approach to take with a large program, it is not the most efficient. As you'll see shortly, when you run the Microsoft C Compiler with the -Gw switch (the Windows switch), the compiler adds some extra prolog code to all far functions. Only those functions actually called by Windows (such as window procedures or call-back functions) need this prolog code, however. When all the functions in your program are far functions (as they are in the medium model), this extra code can add up to a significant waste of space.

There are several solutions to this problem. The first is fairly simple. When compiling a module that does not include any functions that are called from Windows (such as window procedures, dialog procedures, or call-back functions), compile with the -GW switch rather than the -Gw switch. This reduces the prolog code on far functions.

Another approach to reduce wasted space in a medium-model program is to define all functions used only within a module as near functions. Another solution is to use a mixed model with a small model as a base. Let's assume you have five source code modules:

Module 1 contains WinMain, the message loop, your window procedure, and most message processing.

Module 2 contains one function that has all initialization code. This function is called by WinMain from Module 1 before entering the message loop.

Module 3 contains one function called from your window procedure and several other functions called only within this module.

Module 4 also contains a function called from your window procedure and several other functions called only within this module. This module also calls a function in Module 5.

Module 5 contains a function called from Module 4 and several other functions called only within this module.

You can organize this program into four segments, with Modules 4 and 5 in a single segment. Within each module, you explicitly define as far any function called from outside the segment. This involves one function each in Modules 2, 3, and 4. In the modules that call these functions, the functions must be declared as far using the function name prefaced by FAR near the top of the program.

You compile each module for the small model, except that you assign one code segment name to Module 2, another to Module 3, and yet another to Modules 4 and 5. These names are assigned by including the -NT (”name the text segment“) switch when compiling. Each module with the same code segment name is in the same segment. Now you have far functions only where you need them—for functions that are called from another segment.

As you can see, this mixed-model approach is more of a headache than the medium-model approach. It requires that you figure out which functions must be declared far and which can be near. It also has an additional problem: You can call normal C library routines from only one segment—the segment that gets the default segment name _TEXT when you compile without the -NT switch.