___________________________________________________________________________
Windows memory management
CONTENTS
___________________________________________________________________________
Windows memory
management
Running out of memory . . . .
Memory models . . . . . . . .
The '86 registers . . . . .
General-purpose registers
Segment registers . . . .
Special-purpose registers
The flags register . . . .
Memory segmentation . . . .
Pointers . . . . . . . . . .
Near pointers . . . . . .
Far pointers . . . . . . .
Huge pointers . . . . . .
The four memory models . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
2
2
2
2
3
3
4
4
4
5
5
14
===========================================================================
Running out of memory
===========================================================================
Borland C++ does not generate any intermediate data
structures to disk when it is compiling (Borland C++
writes only .OBJ files to disk); instead it uses RAM
for intermediate data structures between passes.
Because of this, you might encounter the message "Out
of memory" if there is not enough memory available for
the compiler.
The solution to this problem is to make your functions
smaller, or to split up the file that has large
functions.
===========================================================================
Memory models
===========================================================================
Borland C++ gives you four memory models, each suited
for different program and code sizes. Each memory model
uses memory differently. What do you need to know to
use memory models? To answer that question, we have to
- 1 -
See page 5 for a take a look at the computer system you're working on.
summary of each Its central processing unit (CPU) is a microprocessor
memory model. belonging to the Intel iAPx86 family; an 80286, 80386,
or 80486. For now, we'll just refer to it as an '86.
The '86 registers =======================================================
These are some of the registers found in the '86
processor. There are other registers--but they can't be
accessed directly, so they're not shown here.
Figure not available online
'86 registers
------------------ The general-purpose registers are the ones used most
General-purpose often to hold and manipulate data. Each has some
registers special functions that only it can do. For example,
-----------------o Some math operations can only be done using AX.
o BX can be used as an index register.
o CX is used by LOOP and some string instructions.
o DX is implicitly used for some math operations.
But there are many operations that all these registers
can do; in many cases, you can freely exchange one for
another.
------------------ The segment registers hold selectors which reference
Segment registers segment descriptors. These descriptors provide
------------------ information about the starting address of the segment,
size, access control, and use.
------------------ The '86 also has some special-purpose registers:
Special-purpose
registers o The SI and DI registers can do many of the things the
-----------------general-purpose registers can, plus they are used as
index registers. They're also used by Borland C++ for
register variables.
o The SP register points to the current top-of-stack
and is an offset into the stack segment.
o The BP register is a secondary stack pointer, usually
used to index into the stack in order to retrieve
arguments or automatic variables.
Borland C++ functions use the base pointer (BP)
register as a base address for arguments and automatic
- 2 -
Memory =======================================================
segmentation
- 3 -
- 4 -
Medium. Far pointers are used for code, but not for
data. As a result, data plus stack are limited to 64K,
but code is limited only to the amount of directly
addressable memory.
Best if code is
small but needs to
address a lot of
data.
Large is needed
only for very
large
applications.
Large. Far pointers are used for both code and data,
giving both a range limited only by the amount of
directly addressable memory. Static data and the stack
are still limited to 64K.
Figures 1.3 through 1.6 show how memory in the '86 is
apportioned for the Borland C++ memory models. To
select these memory models, you can either use menu
- 5 -
- 6 -
===========================================================================
Mixed-model programming: Addressing modifiers
===========================================================================
Borland C++ introduces eight new keywords not found in
standard ANSI C (near, far, huge, _cs, _ds, _es, _ss,
and _seg) that can be used as modifiers to pointers
(and in some cases, to functions), with certain
limitations and warnings.
In Borland C++, you can modify the declarations of
pointers, objects, and functions with the keywords
near, far, or huge. We explained near, far, and huge
data pointers earlier in this chapter. You can declare
far objects using the far keyword. near functions are
invoked with near calls and exit with near returns.
Similarly, far functions are called far and do far
returns. huge functions are like far functions, except
that huge functions set DS to a new value, while far
functions do not.
There are also four special near data pointers: _cs,
_ds, _es, and _ss. These are 16-bit pointers that are
specifically associated with the corresponding segment
register. For example, if you were to declare a pointer
to be
char _ss *p;
then p would contain a 16-bit offset into the stack
segment.
Functions and pointers within a given program default
to near or far, depending on the memory model you
select. If the function or pointer is near, it is
automatically associated with either the CS or DS
register.
The next table shows just how this works. Note that the
size of the pointer corresponds to whether it is
working within a 64K memory limit (near, within a
segment) or inside the general 1 MB memory space (far,
has its own segment address).
Pointer results
------------------------------------------------------Memory model
Function pointers Data pointers
------------------------------------------------------Small
Medium
Compact
Large
near, _cs
far
near, _cs
far
near, _ds
near, _ds
far
far
- 7 -
- 8 -
- 9 -
void myputs(s)
char *s;
{
}
main()
{
char near *mystr;
mystr = "Hello, world\n";
myputs(mystr);
}
- 10 -
-----------------Pointing to a
given
segment:offset
address
------------------
MK_FP(segment_value, offset_value)
Given a far pointer, fp, you can get the segment
component with FP_SEG(fp) and the offset component with
FP_OFF(fp). For more information about these three
Borland C++ library routines, refer to the Library
Reference.
- 11 -
#include <stdio.h>
#include "myputs.h"
main()
{
char near *mystr;
mystr = "Hello, world\n";
- 12 -
myputs(mystr);
}
When you compile this program, Borland C++ reads in the
function prototype from myputs.h and sees that it is a
far function that expects a far pointer. Because of
that, it will generate the proper calling code, even if
it's compiled using the small memory model.
What if, on top of all this, you need to link in
library routines? Your best bet is to use one of the
large model libraries and declare everything to be far.
To do this, make a copy of each header file you would
normally include (such as stdio.h), and rename the copy
to something appropriate (such as fstdio.h).
Then edit each function prototype in the copy so that
it is explicitly far, like this:
int far cdecl printf(char far * format, ...);
That way, not only will far calls be made to the
routines, but the pointers passed will be far pointers
as well. Modify your program so that it includes the
new header file:
Note that this
program uses the
EasyWin library.
#include <fstdio.h>
main()
{
char near *mystr;
mystr = "Hello, world\n";
printf(mystr);
}
Compile your program with the command-line compiler BCC
then link it with TLINK, specifying a large model
library, such as CWL.LIB. Mixing models is tricky, but
it can be done; just be prepared for some difficult
bugs if you do things wrong.
- 13 -
INDEX
___________________________________________________________________________
'86 processors
registers 2-3
A
auxiliary carry flag 3
AX register 2
B
base address register 2
BP register 2
BX register 2
C
carry flag 3
code segment 4
command-line compiler
options
data segment
name 9
far objects (-zE
-zF
and -zH) 9
-zX (code and data segments) 9
_cs (keyword) 7
CS register 4
CX register 2
D
data segment
naming and renaming 9
data segments 4
descriptors
segment 2
DI register 2
direction flag 3
_ds (keyword) 7
DS register 4
DX register 2
E
errors
out of memory 1
_es (keyword) 7
ES register 4
extra segment 4
F
far (keyword) 4, 7, 13
flags
register 2, 3
FP_OFF 11
FP_SEG 11
functions
declaring
as near or far 9
far
declaring 10
memory model size and 9
near
declaring 10
memory models and 9
recursive
memory models and 9
H
huge (keyword) 4, 7
I
interrupts
flag 3
IP (instruction pointer) register 2
L
linker
mixed modules and 12
using directly 12
M
macros
far pointer creation 11
MK_FP 11
memory
Borland C++'s usage of 1
memory models and 6
Index
14
memory addresses
calculating 2
far pointers and 4
near pointers and 4
pointing to 11
memory models 6, 1-13
changing 11
compact 5
comparison 6
defined 5
illustrations 6
large 5
medium 5
memory apportionment and 6
mixing 12
function prototypes and 12
pointers and 4, 7
small 5
Windows and 5
mixed modules
linking 12
MK_FP (run-time library macro) 11
modifiers
pointers 8
modules
linking mixed 12
size limit 6
N
near (keyword) 4, 7
negative offsets 3
O
objects
far
class names 9
declaring 9
option pragma and 9
offsets
component of a pointer 11
option pragma
far objects and 9
out of memory error 1
overflows
flag 3
P
parity flag 3
pointers
arithmetic 5
changing memory models and 11
comparing 5
default data 6
far
adding values to 5
declaring 10-11
function prototypes and 11
memory model size and 10
registers and 4
far memory model and 4
huge 5
declaring 10-11
huge memory model and 4
memory models and 4, 7
to memory addresses 11
modifiers 7
near
declaring 10-11
function prototypes and 11
memory model size and 10
registers and 4
near memory model and 4
normalized 5
segment 7, 8
stack 2
positive offsets 3
#pragma directives
option pragma
far objects and 9
prototypes
far and near pointers and 11
mixing modules and 12
R
RAM
Borland C++'s use of 1
recursive functions
memory models and 9
registers
'86 2-3
AX 2
base point 2
BP 2
BX 2
CS 4
CX 2
DI 2
DS 4
DX 2
ES 4
flags 2, 3
index 2
IP (instruction pointer) 2
LOOP and string instruction 2
- 15 -
math operations 2
segment 2, 4
SI 2
SP 2
special-purpose 2
SS 4
S
_seg (keyword) 7, 8
segment descriptors 2
segment:offset address notation
making far pointers from 11
segmented memory architecture 4
segments 5
component of a pointer 11
memory 4
pointers 7, 8
registers 2, 4
selectors 2
SI register 2
sign
flag 3
SP register 2
special-purpose registers ('86) 2
SS register 4
_ss (keyword) 7
stack
pointers 2
segment 4
strings
instructions
registers 2
T
TLINK (linker)
using directly 12
trap flag 3
Z
zero flag 3
-zX options (code and data
segments) 9
Index
16