16-bit Memory Models

This chapter describes the various 16-bit memory models supported by Watcom C/C++. Each memory model is distinguished by two properties: the code model used to implement function calls, and the data model used to reference data.

This chapter includes the following sections:

16-bit Code Models

There are two code models:

the small code model
A small code model is one in which all calls to functions are made with near calls. In a near call, the destination address is 16 bits and is relative to the segment value in segment register CS. Hence, in a small code model, all code comprising your program, including library functions, must be less than 64K.
the big code model
A big code model is one in which all calls to functions are made with far calls. In a far call, the destination address is 32 bits (consisting of a segment value and an offset relative to the segment value). This model allows the size of the code comprising your program to exceed 64K.
If your program contains less than 64K of code, you should use a memory model that employs the small code model. This will result in smaller and faster code, since near calls are smaller instructions and are processed faster by the CPU.

16-bit Data Models

There are three data models:

the small data model
A small data model is one in which all references to data are made with near pointers. Near pointers are 16 bits; all data references are made relative to the segment value in segment register DS. Hence, in a small data model, all data comprising your program must be less than 64K.
the big data model
A big data model is one in which all references to data are made with far pointers. Far pointers are 32 bits (consisting of a segment value and an offset relative to the segment value). This removes the 64K limitation on data size imposed by the small data model. However, when a far pointer is incremented, only the offset is adjusted. Watcom C/C++ assumes that the offset portion of a far pointer won't be incremented beyond 64K.

The compiler assigns an object to a new segment if the grouping of data in a segment causes the object to cross a segment boundary. Implicit in this is the requirement that no individual object exceed 64K bytes. For example, an array containing 40,000 integers doesn't fit into the big data model. An object such as this should be described as huge.

the huge data model
A huge data model is one in which all references to data are made with far pointers. This is similar to the big data model. However, in the huge data model, incrementing a far pointer adjusts the offset and the segment if necessary. The limit on the size of an object pointed to by a far pointer imposed by the big data model is removed in the huge data model.
  1. If your program contains less than 64K of data, you should use the small data model. This will result in smaller and faster code, since references using near pointers produce fewer instructions.
  2. The huge data model should be used only if needed. The code generated in the huge data model isn't very efficient, since a run-time routine is called in order to increment far pointers. This increases the size of the code significantly, and increases execution time.

Summary of 16-bit Memory Models

As previously mentioned, a memory model is a combination of a code model and a data model. The following table describes the memory models supported by Watcom C/C++.

Memory Model Code Model Data Model Default Code Pointer Default Data Pointer
smallsmallsmallnearnear
mediumbigsmallfarnear
compactsmallbignearfar
largebigbigfarfar
hugebighugefarhuge

Mixed 16-bit Memory Model

A mixed memory model application combines elements from the various code and data models. A mixed memory model application might be characterized as one that uses the near, far, or huge keywords when describing some of its functions or data objects.

For example, a medium memory model application that uses some far pointers to data can be described as a mixed memory model. In an application such as this, most of the data is in a 64K segment (DGROUP), and hence can be referenced with near pointers relative to the segment value in segment register DS. This results in the generation of more efficient code, and better execution times than one can expect from a big data model. Data objects outside of the DGROUP segment are described with the far keyword.

Linking Applications for the Various 16-bit Memory Models

Each memory model requires different run-time and floating-point libraries. Each library assumes a particular memory model, and should be linked only with modules that have been compiled with the same memory model. The following table lists the libraries that are to be used to link an application that has been compiled for a particular memory model.

Memory Model Run-time Library Floating-Point Calls Library Floating-Point Library (80x87)
small clibs.lib maths.lib math87s.lib, (no)emu87.lib
medium clibm.lib mathm.lib math87m.lib, (no)emu87.lib
compact clibc.lib mathc.lib math87c.lib, (no)emu87.lib
large clibl.lib mathl.lib math87l.lib, (no)emu87.lib
huge clibh.lib mathh.lib math87h.lib, (no)emu87.lib
One of emu87.lib or noemu87.lib will be used with the 80x87 math libraries, depending on the use of the fpi (include emulation) or fpi87 (don't include emulation) options.

Memory Layout

The following describes the segment ordering of an application linked by the Watcom Linker. Note that this assumes that the DOSSEG linker option has been specified.

  1. all segments not belonging to group DGROUP with class CODE
  2. all other segments not belonging to group DGROUP
  3. all segments belonging to group DGROUP with class BEGDATA
  4. all segments belonging to group DGROUP not with class BEGDATA, BSS or STACK
  5. all segments belonging to group DGROUP with class BSS
  6. all segments belonging to group DGROUP with class STACK

A special segment belonging to class BEGDATA is defined when linking with Watcom run-time libraries. This segment is initialized with the hexadecimal byte pattern 01, and is the first segment in group DGROUP, so that storing data at location 0 can be detected.

Segments belonging to class BSS contain uninitialized data. Note that this only includes uninitialized data in segments belonging to group DGROUP. Segments belonging to class STACK are used to define the size of the stack used for your application. Segments belonging to the classes BSS and STACK are last in the segment ordering, so that uninitialized data need not take space in the executable file.

In addition to these special segments, the following conventions are used by Watcom C/C++:

  1. The CODE class contains the executable code for your application. In a small code model, this consists of the segment _TEXT. In a big code model, this consists of the segment module_TEXT, where module is the file name of the source file.
  2. The FAR_DATA class consists of the following:
    • data objects whose size exceeds the data threshold in large data memory models (the data threshold is 32K unless changed using the zt compiler option)
    • data objects defined using the FAR or HUGE keyword
    • literals whose size exceeds the data threshold in large data memory models (the data threshold is 32K unless changed using the zt compiler option)
    • literals defined using the FAR or HUGE keyword.

You can override the default naming convention used by Watcom C/C++ to name segments.

  1. The nm option for the Watcom C/C++ compiler can be used to change the name of the module. This, in turn, changes the name of the code segment when compiling for a big code model.
  2. The nt option for the Watcom C/C++ compiler can be used to specify the name of the code segment, regardless of the code model used.