MEMORY ORGANIZATION IN WINDOWS

The entire memory area that Windows controls is called ”global memory“ or the ”global heap.“ This area begins at the location where MS-DOS first loads Windows into memory and ends at the top of available memory, which most often is the top of physical memory. (In C programming, the word global usually refers to variables or functions in one source code file that can be referenced from functions in another source code file of the same program. That is not the meaning of global here. In this discussion of Windows' memory organization, the word global instead means ”everything.“) Every block of memory allocated from the global heap is a segment. Global memory not currently allocated is called ”free memory.“

A Windows program can have one or more code segments and one or more data segments. (The example programs shown in this book have only one of each.) When Windows loads a program into memory, it allocates at least one segment from the global heap for code and one segment for data. When the program begins to execute, the microprocessor's CS register is set to the segment address of the code segment that contains the entry point of the program. The DS and SS registers are set to the segment address of the program's automatic, or default, data segment, which is the data segment that contains the stack. (The combination of the data and the stack into one segment referenced by both DS and SS is normal for C compilers. DS is used to reference data declared as static; SS is used to reference data on the stack, which includes local nonstatic data and arguments passed to functions. This approach allows near pointers to be used for function parameters. The function doesn't have to know whether it's dealing with static data or stack data. Problems related to unequal DS and SS segment registers are discussed in Chapter 19, ”Dynamic Link Libraries.“)

When loading a program, Windows also allocates two other segments from the global heap for program overhead. One of these segments contains the header portion of the program's .EXE file. This segment is used for all instances of a program, so it is allocated only for the first instance. The other segment contains information unique to each instance, such as the program's command-line string and the program's current subdirectory. When a program loads resources (such as icons, cursors, or menu templates) into memory, each resource gets its own segment in the global heap. A program may itself also allocate some memory from the global heap.

If a program has only one code segment, then any calls it makes to functions within the program are compiled as near calls. The CS code segment register remains the same. However, when a program calls a Windows function, the Windows function is in a different code segment. This situation requires that the program generate a far call, which is the reason that all Windows functions (and all functions within your program that are called by Windows) must be declared as far.

A Windows program that has one data segment can use near pointers to access memory within that data segment. However, when a Windows program passes a pointer to a Windows function, the pointer must be a far (or long) pointer; otherwise, the code that contains the Windows function will use its own data segment. The far pointer is required for the Windows function to access the data within your program's data segment.