Loading....
Coupon Accepted Successfully!

 

Memory Models

The memory model sets the supportable size of code and data areas as shown in Figure. We need to specify an appropriate memory model before compiling and linking the source code. Selection of the memory model is done from the option menu of the C++ editor. The compiler option is selected, and one of the memory models is chosen. Using memory models, we can set the size limits of the data and code. C/C++ programs always use different segments for code and


Fig: Memory organization


data. The memory model you opt for decides the default method of memory addressing, and the default memory model is small. Table describes the properties of all memory models.


Tiny: Use the tiny model when memory is at an absolute premium. All four segment registers (CS, DS, ES, and SS) are initialized with the same address, and all addressing is accomplished using 16 bits. Total memory capacity in this case is 64 Kbytes. In short, memory capacity is abbreviated as KB. This means that the code, data, and stack should fit within the same 64-Kbytes segment. Programs are executed quickly if this model is selected. Near pointers are always used. Tiny model programs can be converted to .COM format.

Small: All codes should fit into a single 64-KB segment, and all data should fit into a second 64-KB segment. All pointers are 16 bits in length. Execution speed is similar to that in the tiny model. This model is used for average-sized programs. Near pointers are always used.

Medium: All data should fit into a single 64-KB segment. However, the code is allowed to use multiple segments. All pointers to data are 16 bits, but all jumps and calls require 32-bit addresses. With this, the access to data is fast. However, slower program execution is observed with this model. This model is suitable for big programs that do not store a large amount of data in memory. Far pointers are used for codes but not for data.

Compact: All codes should fit into a 64-KB segment, but the data can use multiple segments. However, no data item can surpass 64 KB. All pointers to data are 32 bits, but jumps and calls can use 16-bit addresses. Slow access to data and quick code execution will be observed in this setting.

Table: Memory models

 

Sr.No.

Memory Model

Segment

Type of Pointer

Code

Data

Stack

Code

Data

1

Tiny

64 K

near

near

2

Small

64 K

64 K

near

near

3

Medium

1 MB

64 K

far

near

4

Compact

64 K

1 MB

near

far

5

Large

1 MB

1 MB

far

far

6

Huge

1 MB

64K each

64K each

far

far

 
The compact model is preferred if your program is small, but you require to point a large amount of data. The compact model is the opposite of the medium model. Far pointers are used for data but not for code. The code is limited to 64 K, whereas the data have a 1-MB range. All functions are near by default, and all data pointers are far by default.
 
Large: Both code and data are allowed to use multiple segments. All pointers are 32 bits in length. However, no single data item can exceed 64 KB. Code execution is slower.
 
A large model is used for very big programs only. Far pointers are used for both code and data, both of which specify a 1-MB range. All functions and data pointers are far by default.
 
Huge: Both code and data are allowed to use multiple segments. Every pointer is 32 bits in length and it is different from large memory model only by pointer math and not by segments. Because of this huge model, code execution is slowest.
 
Use the Huge model for very big programs only. Far pointers are used for both code and data. Turbo C++ usually bounds the size of all data to 64K. The Huge memory model sets aside that limit, permitting data to hold more than 64K. This model permits multiple data segments (each 64K in size), up to 1 MB for code, and 64K for stack. All functions and data pointers are supposed to be far.

Segment and offset address

Every address has two parts: segment and offset. We can separate these address parts using the following two macros defined in dos.h header file.
 
FP_SEG() – This macro is used to obtain the segment address of the given pointer variable.
FP_OFF() – This macro is used to obtain the offset address of the given pointer variable.
 
The following programs illustrate the working of both these macros.
 

14.1 Write a program to obtain segment and offset address.

#include<dos.h>

#include<iostream.h>

#include<constream.h>

int main()

{

clrscr();

int ch;

cout<<“\n Complete Address of ch:”<<&ch;

cout<<“\n Segment address:”<<hex<<FP_SEG(&ch);

cout<<“\n Offset address:”<<hex<<FP_OFF(&ch);

return 0;

}

OUTPUT
Complete Address of ch : 0x8f34fff2
Segment address : 8f34
Offset address : fff2

Explanation:
In the above program, variable ch is declared. The first cout statement displays the whole address of the variable ch, that is, 0x8f34fff2. The macro FP_SEG() returns the segment address. The statement used is FP_SEG(&ch). Here, the address of ch is passed to the macro. In the same way, the offset address is obtained using the statement FP_OFF(&ch). You can observe the complete address as displayed above. The separated addresses are also similar. Figure 14.2 makes this point clearer.
 

Fig: Segment and offset addresses

 

far, huge, and near are keywords. They are summarized in Table.

Table: Keywords summary
 

Keyword

Data

Code

Pointer Arithmetic

near

16-bit address

16-bit address

16-bit

far

32-bit address

32-bit address

16-bit

huge

32-bit address

Keyword not applicable

32-bit

 
far pointer: A far pointer is a 32-bit pointer that contains both segment and offset address parts.
 
huge pointer: A huge pointer is 32 bits long, and it contains both segment and offset address parts.
 
near pointer: A near pointer is 16 bits long. It uses the contents of the CS or DS register for the segment part. The offset part of the address is stored in 16 bits near the pointer.
 

14.2 Write a program to declare far, near and huge pointer. Display their sizes.

#include<iostream.h>

#include<constream.h>

int main()

{

clrscr();

char far *f; // far pointer declaration

char near *n; // near pointer declaration

char huge *h; // huge pointer declaration

cout<<“\n Size of far pointer:”<<sizeof(f);

cout<<“\n Size of near pointer:”<<sizeof(n);

cout<<“\n Size of huge pointer:”<<sizeof(h);

return 0;

}

OUTPUT

Size of far pointer: 4

Size of near pointer: 2

Size of huge pointer: 4


Explanation:
In the above program, the pointers f, n, and h are declared. In the pointer declaration, the pointers are preceded by the keywords far, near, and huge. The sizeof() operators display the size of the pointers in bytes.
 

14.3 Write a program to use far pointer.

#include<iostream.h>

#include<constream.h>

int main()

{

clrscr();

char far *s; // pointer declaration

s=(char far*)0xB8000000L; // starting address

*s=‘W’; // displays character on the screen

return 0;

}

OUTPUT

W


Explanation:
Character pointer *s, which is a far pointer, is declared. The address 0xB8000000L is assigned to it. It is a starting address outside the data segment. The address is converted into char far* type by applying type casting. The statement *s=‘W’ displays the character ‘W’ on the screen.





Test Your Skills Now!
Take a Quiz now
Reviewer Name