3 Gordon Drive, P.O.Box 1347 Rockland, Maine 04841 U.S.A.
Find Tools for Your Chip


Subscribe to our Newsletter

© 2004 Avocet Systems, Inc.
Call Us Today at 207-596-0080
Avocet Systems, Inc. : The Complete Solution for Embedded Systems Development Tools
Tech Tips
Use of Pointers with the 8051XA Compiler


Introduction

Customers using this compiler have posed various questions to Avocet's technical support department concerning error messages given by the compiler relating to declarations, especially those in respect of pointers. This article aims to provide help on this subject, providing information that was not available in the first edition of the manual and augmenting that provided in the second (which latter is available in electronic format to users registered with Avocet Systems).

Some General Points


Simple pointer declarations follow that described in any text on the C language; as for example in the declaration:

long* pl;

which declares pl as a pointer to a long integer and can be assigned a value typically by an statement such as: long longvar;

pl = &longvar;

However,for many compilers written for embedded controllers additional keywords are provided to facilitate building code for a ROM based application. Let us review the use of these keywords when employed in pointer declarations. For example, if we use the keyword near, then this means that the object so qualified is located in internal RAM below 400H. The declaration:

near int* pni;

declares pni to be a pointer to an integer located in internal RAM below 400H. Note that near refers to the object pointed to, not the pointer itself. If we wished to place the pointer in internal RAM, then we would write the declaration:

int* near npi;

Thus qualifiers placed to the left of the asterisk apply to the object pointed to and those to the right of it, to the pointer itself. Other qualifiers to which this applies are far, code, huge. and persistent. The sample declarations below exemplify their use.

near int* far fpni; /* Far pointer to near integer */

In the above, the use of the far keyword means that pointer may reside in any bank (64K block).

far int * near npfi /* Near pointer to far integer */

Code generated for the use of a far pointer will involve loading a segment register (ES) register, to access the far data object.

far code int * far fpfi; /* Far pointer to far int */

For the above declaration, both the pointer and the integer pointed to can reside in banks other than those currently selected.

far code int * near npfci; /* Near ptr to int in far code space */

Memory Models


Some clarification of pointer characteristics as they relate to the memory model used will be helpful.

Small Model

In small model pointers are 16 bits and have the following characteristics. If the object pointed to lies in the address range of the internal RAM, 00 to 3FF, then the pointer will behave as a pointer to internal RAM. If the address of the object lies above this, then the pointer will act as a pointer to code. The reason for this is that any statically allocated initialized data object is placed in ROM, as opposed to RAM to save data space. You would only use the near qualifier to cause an initalized object to be placed in internal RAM. Other than that, you don't have to use the near and code keywords.

Medium Model

In medium model, pointers access data and address the concatenation of internal RAM and RAM in the current bank; a total of 64K. The far qualifier is used to access objects outside the current bank and can be used in conjunction with the code qualifier. The near qualifier is used to address internal RAM explicitly.

Large Model

Large model is the same as medium model except that code up to 16Mbytes is allowed. The use of pointers is the same as medium model except that the huge qualifier can be applied to pointers to access objects in any bank. Huge pointers are 32 bits. The least signifigant 24 bits are used for the address and the most signifigant bit is set (by the compiler) for access to code and cleared for access to data.

Huge Model

Huge model is the same as large model except that pointers are 32 bits by default.

More Complex Declarations

Some customers' questions on declarations arise concerning more complex declarations, say initializing arrays of pointers to functions etc. As a general rule you can simplify your declarations by using typedefs. As an example, consider the following:

typedef struct { int si; long sl; char* pcc; int

(*pvfil)(int, long); } STRUCTYPE;

You can then make declarations of the form:

far STRUCTYPE * near npfs; STRUCTYPE * far fps;

Additional example material is given below

int fn1(int, long); int fn2(int, long);

typedef struct { int si; long sl; code char* pcc; int (*pvfil)(int, long); } CODESTRUCTYPE;

#pragma strings code

code CODESTRUCTYPE cst[] = {{934, 9345689, "string1", fn1}, {8822, 12345689, "string2", fn2}}; #pragma strings

Notice the use of "#pragma strings code" to place the string constants in ROM.