home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 6.ddi / DOC.ZIP / WINMEM.DOC < prev    next >
Encoding:
Text File  |  1992-06-10  |  41.4 KB  |  1,045 lines

  1. Online document
  2. ___________________________________________________________________________
  3.  
  4.                                                   Windows memory management
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12. CONTENTS
  13. ___________________________________________________________________________
  14.  
  15.  
  16.  
  17.  
  18.  
  19.            Windows memory              Mixed-model programming: Addressing
  20.            management              1   modifiers . . . . . . . . . . . .  7
  21. Running out of memory  . . . . . . 1     Segment pointers  . . . . . . .  8
  22. Memory models  . . . . . . . . . . 1     Declaring far objects . . . . .  9
  23.   The '86 registers  . . . . . . . 2     Declaring functions to be near or
  24.     General-purpose registers  . . 2     far . . . . . . . . . . . . . .  9
  25.     Segment registers  . . . . . . 2     Declaring pointers to be near,
  26.     Special-purpose registers  . . 2     far, or huge  . . . . . . . . . 10
  27.     The flags register . . . . . . 3       Pointing to a given
  28.   Memory segmentation  . . . . . . 3       segment:offset address  . . . 11
  29.   Pointers . . . . . . . . . . . . 4     Using library files . . . . . . 12
  30.     Near pointers  . . . . . . . . 4     Linking mixed modules . . . . . 12
  31.     Far pointers . . . . . . . . . 4
  32.     Huge pointers  . . . . . . . . 5   Index                             14
  33.   The four memory models . . . . . 5
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.                     This document covers
  41.  
  42.     See Chapter 8,  o What to do when you receive "Out of memory" errors.
  43.        "Building a
  44.            Windows  o What memory models are: how to choose one, and why
  45.   application," in    you would (or wouldn't) want to use a particular
  46.   the User's Guide    memory model.
  47. for information on
  48.  choosing a memory
  49.  model for Windows
  50.           modules.
  51.  
  52.  
  53.  
  54. ===========================================================================
  55. Running out of memory
  56. ===========================================================================
  57.  
  58.                     Borland C++ does not generate any intermediate data
  59.                     structures to disk when it is compiling (Borland C++
  60.                     writes only .OBJ files to disk); instead it uses RAM
  61.                     for intermediate data structures between passes.
  62.                     Because of this, you might encounter the message "Out
  63.                     of memory" if there is not enough memory available for
  64.                     the compiler.
  65.  
  66.                     The solution to this problem is to make your functions
  67.                     smaller, or to split up the file that has large
  68.                     functions.
  69.  
  70.  
  71.  
  72. ===========================================================================
  73. Memory models
  74. ===========================================================================
  75.  
  76.                     Borland C++ gives you four memory models, each suited
  77.                     for different program and code sizes. Each memory model
  78.                     uses memory differently. What do you need to know to
  79.                     use memory models? To answer that question, we have to
  80.  
  81.  
  82.  
  83.                                    - 1 -
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.   See page 5 for a  take a look at the computer system you're working on.
  91.    summary of each  Its central processing unit (CPU) is a microprocessor
  92.      memory model.  belonging to the Intel iAPx86 family; an 80286, 80386,
  93.                     or 80486. For now, we'll just refer to it as an '86.
  94.  
  95.  
  96.  The '86 registers  =======================================================
  97.  
  98.                     These are some of the registers found in the '86
  99.                     processor. There are other registers--but they can't be
  100.                     accessed directly, so they're not shown here.
  101.  
  102.                                   Figure not available online
  103.    '86 registers
  104.  
  105.  
  106. ------------------  The general-purpose registers are the ones used most
  107.    General-purpose  often to hold and manipulate data. Each has some
  108.          registers  special functions that only it can do. For example,
  109. ------------------
  110.                     o Some math operations can only be done using AX.
  111.  
  112.                     o BX can be used as an index register.
  113.  
  114.                     o CX is used by LOOP and some string instructions.
  115.  
  116.                     o DX is implicitly used for some math operations.
  117.  
  118.                     But there are many operations that all these registers
  119.                     can do; in many cases, you can freely exchange one for
  120.                     another.
  121.  
  122.  
  123. ------------------  The segment registers hold selectors which reference
  124.  Segment registers  segment descriptors. These descriptors provide
  125. ------------------  information about the starting address of the segment,
  126.                     size, access control, and use.
  127.  
  128. ------------------  The '86 also has some special-purpose registers:
  129.    Special-purpose
  130.          registers  o The SI and DI registers can do many of the things the
  131. ------------------    general-purpose registers can, plus they are used as
  132.                       index registers. They're also used by Borland C++ for
  133.                       register variables.
  134.  
  135.                     o The SP register points to the current top-of-stack
  136.                       and is an offset into the stack segment.
  137.  
  138.                     o The BP register is a secondary stack pointer, usually
  139.                       used to index into the stack in order to retrieve
  140.                       arguments or automatic variables.
  141.  
  142.                     Borland C++ functions use the base pointer (BP)
  143.                     register as a base address for arguments and automatic
  144.  
  145.  
  146.  
  147.                                    - 2 -
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.                     variables. Parameters have positive offsets from BP,
  155.                     which vary depending on the memory model. BP points to
  156.                     the saved previous BP value if there is a stack frame.
  157.                     Functions that have no arguments will not use or save
  158.                     BP if the Standard Stack Frame option is Off.
  159.  
  160.                     Automatic variables are given negative offsets from BP.
  161.                     The offsets depend on how much space has already been
  162.                     assigned to local variables.
  163.  
  164.  
  165. ------------------  The 16-bit flags register contains all pertinent
  166. The flags register  information about the state of the '86 and the results
  167. ------------------  of recent instructions.
  168.  
  169.                     For example, if you wanted to know whether a
  170.                     subtraction produced a zero result, you would check the
  171.                     zero flag (the Z bit in the flags register) immediately
  172.                     after the instruction; if it were set, you would know
  173.                     the result was zero. Other flags, such as the carry and
  174.                     overflow flags, similarly report the results of
  175.                     arithmetic and logical operations.
  176.  
  177.                                   Figure not available online
  178.   Flags register
  179.       of the '86    Other flags control modes of operation of the '86. The
  180.                     direction flag controls the direction in which the
  181.                     string instructions move, and the interrupt flag
  182.                     controls whether external hardware, such as a keyboard
  183.                     or modem, is allowed to halt the current code temporar-
  184.                     ily so that urgent needs can be serviced. The trap flag
  185.                     is used only by software that debugs other software.
  186.  
  187.                     The flags register isn't usually modified or read
  188.                     directly. Instead, the flags register is generally
  189.                     controlled through special assembler instructions (such
  190.                     as CLD, STI, and CMC) and through arithmetic and
  191.                     logical instructions that modify certain flags.
  192.                     Likewise, the contents of certain bits of the flags
  193.                     register affect the operation of instructions such as
  194.                     JZ, RCR, and MOVSB. The flags register is not really
  195.                     used as a storage location, but rather holds the status
  196.                     and control data for the '86.
  197.  
  198.  
  199.             Memory  =======================================================
  200.       segmentation
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.                                    - 3 -
  212.  
  213.  
  214.  
  215.  
  216.  
  217.  
  218.                     The Intel '86 microprocessor has a segmented memory
  219.                     architecture. It has a total address space of 16MB, but
  220.      The 80386 and  it is designed to directly address only 64K of memory
  221.   80486 processors  at a time.
  222.    actually have a
  223.      total address  o The '86 keeps track of four different segments: code,
  224.      space of four    data, stack, and extra. The code segment is where the
  225.      gigabytes and    machine instructions are; the data segment, where
  226.     their segments    information is; the stack is, of course, the stack;
  227.      needn't be as    and the extra segment is also used for extra data.
  228.  small as 64K, but
  229.        Windows 3.x  o The '86 has four 16-bit segment registers (one for
  230. doesn't change the    each segment) named CS, DS, SS, and ES; these point
  231.      segment size.    to the code, data, stack, and extra segments,
  232.                       respectively.
  233.  
  234.  
  235.           Pointers  =======================================================
  236.  
  237.                     Although you can declare a pointer or function to be a
  238.                     specific type regardless of the model used, by default
  239.                     the type of memory model you choose determines the
  240.                     default type of pointers used for code and data.
  241.                     Pointers come in four flavors: near (16 bits), far (32
  242.                     bits), huge (also 32 bits), and segment (16 bits).
  243.  
  244.  
  245. ------------------  A near pointer (16 bits) relies on one of the segment
  246.      Near pointers  registers to
  247. ------------------  specify the address. For example, a pointer to a
  248.                     function would take on the segment of the code segment
  249.                     (CS) register. In a similar fashion, a near data
  250.                     pointer contains an offset to the data segment (DS)
  251.                     register. Near pointers are easy to manipulate, since
  252.                     any arithmetic (such as addition) can be done without
  253.                     worrying about the segment.
  254.  
  255.  
  256. ------------------  A far pointer (32 bits) contains not only the offset
  257.       Far pointers  within the segment, but also the segment address (as
  258. ------------------  another 16-bit value). By using far pointers, you can
  259.                     have multiple code segments; that, in turn, allows you
  260.                     to have programs larger than 64K. You can also address
  261.                     more than 64K of data.
  262.  
  263.                     The equals (==) and not-equal (!=) operators use the
  264.                     32-bit value as an unsigned long. The comparison
  265.                     operators (<=, >=, <, and >) use just the offset.
  266.  
  267.                     The == and != operators need all 32 bits, so the
  268.                     computer can compare to the NULL pointer (0000:0000).
  269.                     If you used only the offset value for equality
  270.  
  271.  
  272.  
  273.  
  274.  
  275.                                    - 4 -
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282.                     checking, any pointer with 0000 offset would be equal
  283.                     to the NULL pointer, which is not what you want.
  284.  
  285.         Important!  If you add values to a far pointer, only the offset is
  286.                     changed. If you add enough to cause the offset to
  287.                     exceed FFFF (its maximum possible value), the pointer
  288.                     just wraps around back to the beginning of the segment.
  289.                     For example, if you add 1 to 150D:FFFF, the result
  290.                     would be 150D:0000. Likewise, if you subtract 1 from
  291.                     150D:0000, you would get 150D:FFFF.
  292.  
  293.                     If you want to do pointer comparisons, it's safest to
  294.                     use either near pointers--which all use the same
  295.                     segment address--or huge pointers, described next.
  296.  
  297.  
  298. ------------------  Huge pointers are also 32 bits long. Like far pointers,
  299.      Huge pointers  they contain both a segment address and an offset.
  300. ------------------  Unlike far pointers, when doing address calculations,
  301.                     the segment is adjusted if necessary.
  302.  
  303.  
  304.    The four memory  =======================================================
  305.             models
  306.                     Borland C++ gives you four memory models: small,
  307.                     medium, compact, and large. Your program requirements
  308.                -->  determine which one you pick. (See Chapter 8, "Building
  309.                     a Windows application," in the User's Guide for
  310.                     information on choosing a memory model for Windows
  311.                     modules.) Here's a brief summary of each:
  312.  
  313.     This is a good  Small. The code and data segments are different and
  314.   size for average  don't overlap, so you have 64K of code and 64K of data
  315.      applications.  and stack. Near pointers are always used.
  316.  
  317.     Best for large  Medium. Far pointers are used for code, but not for
  318.   programs without  data. As a result, data plus stack are limited to 64K,
  319.       much data in  but code is limited only to the amount of directly
  320.            memory.  addressable memory.
  321.  
  322.    Best if code is  Compact. The inverse of medium: Far pointers are used
  323. small but needs to  for data, but not for code. Code is then limited to
  324.   address a lot of  64K, while data is limited only to the amount of
  325.              data.  directly addressable memory. Static data and the stack
  326.                     are still limited to 64K.
  327.  
  328.    Large is needed  Large. Far pointers are used for both code and data,
  329.      only for very  giving both a range limited only by the amount of
  330.              large  directly addressable memory. Static data and the stack
  331.      applications.  are still limited to 64K.
  332.  
  333.                     Figures 1.3 through 1.6 show how memory in the '86 is
  334.                     apportioned for the Borland C++ memory models. To
  335.                     select these memory models, you can either use menu
  336.  
  337.  
  338.  
  339.                                    - 5 -
  340.  
  341.  
  342.  
  343.  
  344.  
  345.  
  346.                     selections from the IDE, or you can type options
  347.                     invoking the command-line compiler version of Borland
  348.                     C++.
  349.  
  350.  
  351.                                   Figure not available online
  352.      Small model
  353.           memory
  354.     segmentation                  Figure not available online
  355.     Medium model
  356.           memory
  357.     segmentation                  Figure not available online
  358.    Compact model
  359.                   
  360.                                   Figure not available online
  361.  CS points to only
  362.     one sfile at a  Table 1.1 summarizes the different models and how they
  363.               time  compare to one another. The models are often grouped
  364.                     according to whether their code or data models are
  365.                     small (64K) or large (16 MB); these groups correspond
  366.                     to the rows and columns in Table 1.1.
  367.  CS points to only
  368.     one sfile at a
  369.               time  -------------------------------------------------------
  370.  small code models                               Code size
  371.        because, by   Data size --------------------------------------------
  372.      default, code                  64K                 16MB/4GB
  373. pointers are near;
  374.  likewise, compact  -------------------------------------------------------
  375.      and large are
  376.  large data models
  377.        because, by   64K    Small (no overlap;    Medium (small data,
  378.      default, data          total size = 128K)    large code)
  379.  pointers are far.
  380.                     -------------------------------------------------------
  381.  
  382.  
  383.                      16MB   Compact (large data,  Large (large data,
  384.                      /4GB   small code)           large code)")
  385.  
  386.  
  387.                     -------------------------------------------------------
  388.  
  389.         Important!  When you compile a module (a given source file with
  390.                     some number of routines in it), the resulting code for
  391.                     that module cannot be greater than 64K, since it must
  392.                     all fit inside of one code segment. This is true even
  393.                     if you're using one of the larger code models (medium
  394.                     or large). If your module is too big to fit into one
  395.                     (64K) code segment, you must break it up into different
  396.                     source code files, compile each file separately, then
  397.                     link them together.
  398.  
  399.  
  400.  
  401.  
  402.  
  403.                                    - 6 -
  404.  
  405.  
  406.  
  407.  
  408.  
  409.  
  410. ===========================================================================
  411. Mixed-model programming: Addressing modifiers
  412. ===========================================================================
  413.  
  414.                     Borland C++ introduces eight new keywords not found in
  415.                     standard ANSI C (near, far, huge, _cs, _ds, _es, _ss,
  416.                     and _seg) that can be used as modifiers to pointers
  417.                     (and in some cases, to functions), with certain
  418.                     limitations and warnings.
  419.  
  420.                     In Borland C++, you can modify the declarations of
  421.                     pointers, objects, and functions with the keywords
  422.                     near, far, or huge. We explained near, far, and huge
  423.                     data pointers earlier in this chapter. You can declare
  424.                     far objects using the far keyword. near functions are
  425.                     invoked with near calls and exit with near returns.
  426.                     Similarly, far functions are called far and do far
  427.                     returns. huge functions are like far functions, except
  428.                     that huge functions set DS to a new value, while far
  429.                     functions do not.
  430.  
  431.                     There are also four special near data pointers: _cs,
  432.                     _ds, _es, and _ss. These are 16-bit pointers that are
  433.                     specifically associated with the corresponding segment
  434.                     register. For example, if you were to declare a pointer
  435.                     to be
  436.  
  437.                        char _ss *p;
  438.  
  439.                     then p would contain a 16-bit offset into the stack
  440.                     segment.
  441.  
  442.                     Functions and pointers within a given program default
  443.                     to near or far, depending on the memory model you
  444.                     select. If the function or pointer is near, it is
  445.                     automatically associated with either the CS or DS
  446.                     register.
  447.  
  448.                     The next table shows just how this works. Note that the
  449.                     size of the pointer corresponds to whether it is
  450.                     working within a 64K memory limit (near, within a
  451.                     segment) or inside the general 1 MB memory space (far,
  452.                     has its own segment address).
  453.  
  454.  Pointer results
  455.                     -------------------------------------------------------
  456.                      Memory model        Function pointers   Data pointers
  457.                     -------------------------------------------------------
  458.  
  459.                        Small                 near, _cs         near, _ds
  460.                        Medium                far               near, _ds
  461.                        Compact               near, _cs         far
  462.                        Large                 far               far
  463.  
  464.  
  465.  
  466.  
  467.                                    - 7 -
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474.                     -------------------------------------------------------
  475.  
  476.  
  477.   Segment pointers  =======================================================
  478.  
  479.                     Use _seg in segment pointer type declarators. The
  480.                     resulting pointers are 16-bit segment pointers. The
  481.                     syntax for _seg is:
  482.  
  483.                        datatype _seg *identifier;
  484.  
  485.                     For example,
  486.  
  487.                        int _seg *name;
  488.  
  489.                     Any indirection through identifier has an assumed
  490.                     offset of 0. In arithmetic involving segment pointers
  491.                     the following rules hold true:
  492.  
  493.                     1. You can't use the ++, - -, +=, or -= operators with
  494.                        segment pointers.
  495.  
  496.                     2. You cannot subtract one segment pointer from
  497.                        another.
  498.  
  499.                     3. When adding a near pointer to a segment pointer, the
  500.                        result is a far pointer that is formed by using the
  501.                        segment from the segment pointer and the offset from
  502.                        the near pointer. Therefore, the two pointers must
  503.                        either point to the same type, or one must be a
  504.                        pointer to void. There is no multiplication of the
  505.                        offset regardless of the type pointed to.
  506.  
  507.                     4. When a segment pointer is used in an indirection
  508.                        expression, it is also implicitly converted to a far
  509.                        pointer.
  510.  
  511.                     5. When adding or subtracting an integer operand to or
  512.                        from a segment pointer, the result is a far pointer,
  513.                        with the segment taken from the segment pointer and
  514.                        the offset found by multiplying the size of the
  515.                        object pointed to by the integer operand. The
  516.                        arithmetic is performed as if the integer were added
  517.                        to or subtracted from the far pointer.
  518.  
  519.                     6. Segment pointers can be assigned, initialized,
  520.                        passed into and out of functions, compared and so
  521.                        forth. (Segment pointers are compared as if their
  522.                        values were unsigned integers.) In other words,
  523.                        other than the above restrictions, they are treated
  524.                        exactly like any other pointer.
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.                                    - 8 -
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.      Declaring far  =======================================================
  539.            objects
  540.                     You can declare far objects in Borland C++. For
  541.                     example,
  542.  
  543.                       int far x = 5;
  544.                       int far z;
  545.                       extern int far y = 4;
  546.                       static long j;
  547.  
  548.                     The command-line compiler options -zE, -zF, and -zH
  549.                     (which can also be set using #pragma option) affect the
  550.                     far segment name, class, and group, respectively. When
  551.                     you change them with #pragma option, you can change
  552.                     them at any time and they apply to any ensuing far
  553.                     object declarations. Thus you could use the following
  554.                     sequence to create a far object in a specific segment:
  555.  
  556.                       #pragma option -zEmysegment -zHmygroup -zFmyclass
  557.                       int far x;
  558.                       #pragma option -zE* -zH* -zF*
  559.  
  560.                     This will put x in segment MYSEGMENT 'MYCLASS' in the
  561.                     group 'MYGROUP', then reset all of the far object items
  562.                     to the default values.
  563.  
  564.  
  565.          Declaring  =======================================================
  566.    functions to be
  567.        near or far  On occasion, you'll want (or need) to override the
  568.                     default function type of your memory model shown in
  569.                     Table 1.1 (page 6).
  570.  
  571.                     For example, suppose you're using the large memory
  572.                     model, but you have a recursive (self-calling) function
  573.                     in your program, like this:
  574.  
  575.                       double  power(double x,int exp)
  576.                       {
  577.                          if (exp <= 0)
  578.                             return(1);
  579.                          else
  580.                             return(x * power(x, exp-1));
  581.                       }
  582.  
  583.                     Every time power calls itself, it has to do a far call,
  584.                     which uses more stack space and clock cycles. By
  585.                     declaring power as near, you eliminate some of the
  586.                     overhead by forcing all calls to that function to be
  587.                     near:
  588.  
  589.                        double  near power(double x,int exp)
  590.  
  591.  
  592.  
  593.  
  594.  
  595.                                    - 9 -
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.                     This guarantees that power is callable only within the
  603.                     code segment in which it was compiled, and that all
  604.                     calls to it are near calls.
  605.  
  606.                     This means that if you are using a large code model
  607.                     (medium or large), you can only call power from within
  608.                     the module where it is defined. Other modules have
  609.                     their own code segment and thus cannot call near
  610.                     functions in different modules. Furthermore, a near
  611.                     function must be either defined or declared before the
  612.                     first time it is used, or the compiler won't know it
  613.                     needs to generate a near call.
  614.  
  615.                     Conversely, declaring a function to be far means that a
  616.                     far return is generated. In the small code models, the
  617.                     far function must be declared or defined before its
  618.                     first use to ensure it is invoked with a far call.
  619.  
  620.                     Look back at the power example. It is wise to also
  621.                     declare power as static, since it should only be called
  622.                     from within the current module. That way, being a
  623.                     static, its name will not be available to any functions
  624.                     outside the module.
  625.  
  626.  
  627. Declaring pointers  =======================================================
  628.   to be near, far,
  629.            or huge  You've seen why you might want to declare functions to
  630.                     be of a different model than the rest of the program.
  631.                     Why might you want to do the same thing for pointers?
  632.                     For the same reasons given in the preceding section:
  633.                     either to avoid unnecessary overhead (declaring near
  634.                     when the default would be far) or to reference
  635.                     something outside of the default segment (declaring far
  636.                     or huge when the default would be near).
  637.  
  638.                     There are, of course, potential pitfalls in declaring
  639.                     functions and pointers to be of nondefault types. For
  640.                     example, say you have the following small model
  641.                     program:
  642.  
  643.     Note that this    void myputs(s)
  644.   program uses the    char *s;
  645.   EasyWin library.    {
  646.                       }
  647.  
  648.                       main()
  649.                       {
  650.                          char near *mystr;
  651.  
  652.                          mystr = "Hello, world\n";
  653.                          myputs(mystr);
  654.                       }
  655.  
  656.  
  657.  
  658.  
  659.                                   - 10 -
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.                     This program works fine. In fact, the near declaration
  667.                     on mystr is redundant, since all pointers, both code
  668.                     and data, will be near.
  669.  
  670.                     But what if you recompile this program using the
  671.                     compact (or large) memory model? The pointer mystr in
  672.                     main is still near (it's still a 16-bit pointer).
  673.                     However, the pointer s in myputs is now far, since
  674.                     that's the default. This means that myputs will pull
  675.                     two words out of the stack in an effort to create a far
  676.                     pointer, and the address it ends up with will certainly
  677.                     not be that of mystr.
  678.  
  679.                     How do you avoid this problem? The solution is to
  680.                     define myputs in modern C style, like this:
  681.  
  682.                       void myputs(char *s)
  683.                       {
  684.                         int i;
  685.  
  686.                         for (i = 0; s[i] != 0; i++)
  687.                           putc(s[i]);
  688.                       }
  689.  
  690. If you're going to  Now when Borland C++ compiles your program, it knows
  691. explicitly declare  that myputs expects a pointer to char; and since you're
  692.  pointers to be of  compiling under the large model, it knows that the
  693.  type far or near,  pointer must be far. Because of that, Borland C++ will
  694.     be sure to use  push the data segment (DS) register onto the stack
  695.           function  along with the 16-bit value of mystr, forming a far
  696. prototypes for any  pointer.
  697.     functions that
  698.    might use them.  How about the reverse case: Arguments to myputs
  699.                     declared as far and compiling with a small data model?
  700.                     Again, without the function prototype, you will have
  701.                     problems, since main will push both the offset and the
  702.                     segment address onto the stack, but myputs will only
  703.                     expect the offset. With the prototype-style function
  704.                     definitions, though, main will only push the offset
  705.                     onto the stack.
  706.  
  707.  
  708. ------------------  How do you make a far pointer point to a given memory
  709.      Pointing to a  location (a specific segment:offset address)? You can
  710.              given  use the macro MK_FP, which takes a segment and an
  711.     segment:offset  offset and returns a far pointer. For example,
  712.            address
  713. ------------------     MK_FP(segment_value, offset_value)
  714.  
  715.                     Given a far pointer, fp, you can get the segment
  716.                     component with FP_SEG(fp) and the offset component with
  717.                     FP_OFF(fp). For more information about these three
  718.                     Borland C++ library routines, refer to the Library
  719.                     Reference.
  720.  
  721.  
  722.  
  723.                                   - 11 -
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.      Using library  =======================================================
  731.              files
  732.                     Borland C++ offers a version of the standard library
  733.                     routines for each of the six memory models. Borland C++
  734.                     is smart enough to link in the appropriate libraries in
  735.                     the proper order, depending on which model you've
  736.                     selected. However, if you're using the Borland C++
  737.                     linker, TLINK, directly (as a standalone linker), you
  738.                     need to specify which libraries to use. See Chapter 4,
  739.                     "TLINK: The Turbo linker" in the Tools and Utilities
  740.                     Guide for details on how to do so.
  741.  
  742.  
  743.      Linking mixed  =======================================================
  744.            modules
  745.                     What if you compiled one module using the small memory
  746.                     model, and another module using the large model, then
  747.                     wanted to link them together? What would happen?
  748.  
  749.                     The files would in some cases link together fine, but
  750.                     the problems you would encounter would be similar to
  751.                     those described in the earlier section, "Declaring
  752.                     functions to be near or far." If a function in the
  753.                     small module called a function in the large module, it
  754.                     would do so with a near call, which would probably be
  755.                     disastrous. Furthermore, you could face the same
  756.                     problems with pointers as described in the earlier
  757.                     section, "Declaring pointers to be near, far, or huge,"
  758.                     since a function in the small module would expect to
  759.                     pass and receive near pointers, while a function in the
  760.                     large module would expect far pointers.
  761.  
  762.                     The solution, again, is to use function prototypes.
  763.                     Suppose that you put myputs into its own module and
  764.                     compile it with the large memory model. Then create a
  765.                     header file called myputs.h (or some other name with a
  766.                     .h extension), which would have the following function
  767.                     prototype in it:
  768.  
  769.                        void far myputs(char far *s);
  770.  
  771.                     Now, if you put main into its own module (called
  772.                     MYMAIN.C), set things up like this:
  773.  
  774.     Note that this    #include <stdio.h>
  775.   program uses the    #include "myputs.h"
  776.   EasyWin library.
  777.                       main()
  778.                       {
  779.                          char near *mystr;
  780.  
  781.                          mystr = "Hello, world\n";
  782.  
  783.  
  784.  
  785.  
  786.  
  787.                                   - 12 -
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.                          myputs(mystr);
  795.                       }
  796.  
  797.                     When you compile this program, Borland C++ reads in the
  798.                     function prototype from myputs.h and sees that it is a
  799.                     far function that expects a far pointer. Because of
  800.                     that, it will generate the proper calling code, even if
  801.                     it's compiled using the small memory model.
  802.  
  803.                     What if, on top of all this, you need to link in
  804.                     library routines? Your best bet is to use one of the
  805.                     large model libraries and declare everything to be far.
  806.                     To do this, make a copy of each header file you would
  807.                     normally include (such as stdio.h), and rename the copy
  808.                     to something appropriate (such as fstdio.h).
  809.  
  810.                     Then edit each function prototype in the copy so that
  811.                     it is explicitly far, like this:
  812.  
  813.                        int far cdecl printf(char far * format, ...);
  814.  
  815.                     That way, not only will far calls be made to the
  816.                     routines, but the pointers passed will be far pointers
  817.                     as well. Modify your program so that it includes the
  818.                     new header file:
  819.  
  820.     Note that this    #include <fstdio.h>
  821.   program uses the
  822.   EasyWin library.    main()
  823.                       {
  824.                          char near *mystr;
  825.                          mystr = "Hello, world\n";
  826.                          printf(mystr);
  827.                       }
  828.  
  829.                     Compile your program with the command-line compiler BCC
  830.                     then link it with TLINK, specifying a large model
  831.                     library, such as CWL.LIB. Mixing models is tricky, but
  832.                     it can be done; just be prepared for some difficult
  833.                     bugs if you do things wrong.
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.                                   - 13 -
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858. INDEX
  859. ___________________________________________________________________________
  860.  
  861.  
  862.  
  863.  
  864.  
  865. '86 processors                          _es (keyword) 7
  866.   registers 2-3                         ES register 4
  867.                                         extra segment 4
  868.  
  869. A
  870. auxiliary carry flag 3                  F
  871. AX register 2                           far (keyword) 4, 7, 13
  872.                                         flags
  873.                                           register 2, 3
  874. B                                       FP_OFF 11
  875. base address register 2                 FP_SEG 11
  876. BP register 2                           functions
  877. BX register 2                             declaring
  878.                                             as near or far 9
  879.                                           far
  880. C                                           declaring 10
  881. carry flag 3                                memory model size and 9
  882. code segment 4                            near
  883. command-line compiler                       declaring 10
  884.   options                                   memory models and 9
  885.     data segment                          recursive
  886.       name 9                                memory models and 9
  887.     far objects (-zE
  888.       -zF
  889.         and -zH) 9                      H
  890.     -zX (code and data segments) 9      huge (keyword) 4, 7
  891. _cs (keyword) 7
  892. CS register 4
  893. CX register 2                           I
  894.                                         interrupts
  895.                                           flag 3
  896. D                                       IP (instruction pointer) register 2
  897. data segment
  898.   naming and renaming 9
  899. data segments 4                         L
  900. descriptors                             linker
  901.   segment 2                               mixed modules and 12
  902. DI register 2                             using directly 12
  903. direction flag 3
  904. _ds (keyword) 7
  905. DS register 4                           M
  906. DX register 2                           macros
  907.                                           far pointer creation 11
  908.                                           MK_FP 11
  909. E                                       memory
  910. errors                                    Borland C++'s usage of 1
  911.   out of memory 1                         memory models and 6
  912.  
  913.  
  914.  
  915. Index                                                                    14
  916.  
  917.  
  918.  
  919.  
  920.  
  921.  
  922. memory addresses                          comparing 5
  923.   calculating 2                           default data 6
  924.   far pointers and 4                      far
  925.   near pointers and 4                       adding values to 5
  926.   pointing to 11                            declaring 10-11
  927. memory models 6, 1-13                       function prototypes and 11
  928.   changing 11                               memory model size and 10
  929.   compact 5                                 registers and 4
  930.   comparison 6                            far memory model and 4
  931.   defined 5                               huge 5
  932.   illustrations 6                           declaring 10-11
  933.   large 5                                 huge memory model and 4
  934.   medium 5                                memory models and 4, 7
  935.   memory apportionment and 6              to memory addresses 11
  936.   mixing 12                               modifiers 7
  937.     function prototypes and 12            near
  938.   pointers and 4, 7                         declaring 10-11
  939.   small 5                                   function prototypes and 11
  940.   Windows and 5                             memory model size and 10
  941. mixed modules                               registers and 4
  942.   linking 12                              near memory model and 4
  943. MK_FP (run-time library macro) 11         normalized 5
  944. modifiers                                 segment 7, 8
  945.   pointers 8                              stack 2
  946. modules                                 positive offsets 3
  947.   linking mixed 12                      #pragma directives
  948.   size limit 6                            option pragma
  949.                                             far objects and 9
  950.                                         prototypes
  951. N                                         far and near pointers and 11
  952. near (keyword) 4, 7                       mixing modules and 12
  953. negative offsets 3
  954.  
  955.                                         R
  956. O                                       RAM
  957. objects                                   Borland C++'s use of 1
  958.   far                                   recursive functions
  959.     class names 9                         memory models and 9
  960.     declaring 9                         registers
  961.     option pragma and 9                   '86 2-3
  962. offsets                                   AX 2
  963.   component of a pointer 11               base point 2
  964. option pragma                             BP 2
  965.   far objects and 9                       BX 2
  966. out of memory error 1                     CS 4
  967. overflows                                 CX 2
  968.   flag 3                                  DI 2
  969.                                           DS 4
  970.                                           DX 2
  971. P                                         ES 4
  972. parity flag 3                             flags 2, 3
  973. pointers                                  index 2
  974.   arithmetic 5                            IP (instruction pointer) 2
  975.   changing memory models and 11           LOOP and string instruction 2
  976.  
  977.  
  978.  
  979.                                   - 15 -
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.   math operations 2                     SP register 2
  987.   segment 2, 4                          special-purpose registers ('86) 2
  988.   SI 2                                  SS register 4
  989.   SP 2                                  _ss (keyword) 7
  990.   special-purpose 2                     stack
  991.   SS 4                                    pointers 2
  992.                                           segment 4
  993.                                         strings
  994. S                                         instructions
  995. _seg (keyword) 7, 8                         registers 2
  996. segment descriptors 2
  997. segment:offset address notation
  998.   making far pointers from 11           T
  999. segmented memory architecture 4         TLINK (linker)
  1000. segments 5                                using directly 12
  1001.   component of a pointer 11             trap flag 3
  1002.   memory 4
  1003.   pointers 7, 8
  1004.   registers 2, 4                        Z
  1005. selectors 2                             zero flag 3
  1006. SI register 2                           -zX options (code and data
  1007. sign                                      segments) 9
  1008.   flag 3
  1009.  
  1010.  
  1011.  
  1012.  
  1013.  
  1014.  
  1015.  
  1016.  
  1017.  
  1018.  
  1019.  
  1020.  
  1021.  
  1022.  
  1023.  
  1024.  
  1025.  
  1026.  
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043. Index                                                                    16
  1044.  
  1045.