Back to ESAcademy Home Page


www.philipsmcu.comUsing pointers, arrays, structures and unions in 8051 C compilers

by Olaf Pfeiffer, ESAcademy
based on the "C51Primer", by Mike Beach, Hitex UK

Pointers and Arrays | Structures and Unions | Generic and Spaced Pointers ]

 

Home

News

Training Classes

Products

Consulting

Technical Library

Contact Us

Recommended Books

Generic Pointers

C51 offers two basic types of pointer, the spaced (memory-specific) and the generic.

As has been mentioned, the 8051 has many physically separate memory spaces, each addressed by special assembler instructions. Such characteristics are not peculiar to the 8051 - for example, the 8086 has data instructions which operate on a 16 bit (within segment) and a 20 bit basis.

For the sake of simplicity, and to hide the real structure of the 8051 from the programmer, C51 uses three byte pointers, rather than the single or two bytes that might be expected. The end result is that pointers can be used without regard to the actual location of the data.

For example:



xdata char buffer[10] ;
code char message[] = { "HELLO" } ; 

void main(void) 
{
char *s ;
char *d ;
   
    s = message ;
    d = buffer ;

    while(*s != '\0') 
    { 
        *d++ = *s++ ;
    }
}

YIELDS THE FOLLOWING CODE:

    RSEG  ?XD?T1 
buffer:            DS  10
    RSEG  ?CO?T1 
message:
    DB  'H' ,'E' ,'L' ,'L' ,'O' ,000H
; 
; 
; xdata char buffer[10] ; 
; code char message[] = { "HELLO" } ; 
; 
;    void main(void) {
    RSEG  ?PR?main?T1
    USING    0
main:
            ; SOURCE LINE # 6
; 
;       char *s ; 
;       char *d ; 
;   
;       s = message ;
            ; SOURCE LINE # 11
    MOV      s?02,#05H
    MOV      s?02+01H,#HIGH message
    MOV      s?02+02H,#LOW message
;       d = buffer ;
            ; SOURCE LINE # 12
    MOV      d?02,#02H
    MOV      d?02+01H,#HIGH buffer
    MOV      d?02+02H,#LOW buffer
?C0001: 
; 
;       while(*s != '\0') { 
            ; SOURCE LINE # 14
    MOV      R3,s?02
    MOV      R2,s?02+01H
    MOV      R1,s?02+02H
    LCALL    ?C_CLDPTR
    JZ       ?C0003
;          *d++ = *s++ ;
            ; SOURCE LINE # 15
    INC      s?02+02H
    MOV      A,s?02+02H
    JNZ      ?C0004
    INC      s?02+01H
?C0004:
    DEC      A
    MOV      R1,A
    LCALL    ?C_CLDPTR
    MOV      R7,A
    MOV      R3,d?02
    INC      d?02+02H
    MOV      A,d?02+02H
    MOV      R2,d?02+01H
    JNZ      ?C0005
    INC      d?02+01H
?C0005:
    DEC      A
    MOV      R1,A
    MOV      A,R7
    LCALL    ?C_CSTPTR
;          }
            ; SOURCE LINE # 16
    SJMP     ?C0001
;       }
            ; SOURCE LINE # 17
?C0003:
    RET      
; END OF main
    END
  

As can be seen, the pointers '*s' and '*d' are composed of three bytes, not two as might be expected. In making *s point at the message in the code space an '05' is loaded into s ahead of the actual address to be pointed at. In the case of *d '02' is loaded. These additional bytes are how C51 knows which assembler addressing mode to use. The library function C_CLDPTR checks the value of the first byte and loads the data, using the addressing instructions appropriate to the memory space being used.

This means that every access via a generic pointer requires this library function to be called. The memory space codes used by C51 are:

CODE - 05
XDATA - 02
PDATA - 03
DATA - 05
IDATA - 01

Spaced Pointers In C51

Considerable run time savings are possible by using spaced pointers. By restricting a pointer to only being able to point into one of the 8051's memory spaces, the need for the memory space "code" byte is eliminated, along with the library routines needed to interpret it.

A spaced pointer is created by:
char xdata *ext_ptr ;

to produce an uncommitted pointer into the XDATA space or
char code *const_ptr ;

which gives a pointer solely into the CODE space. Note that in both cases the pointers themselves are located in the memory space given by the current memory model. A pointer to xdata which is to be itself located in PDATA would be declared as:

pdata char xdata *ext_ptr ;
location of
pointer
mem space
pointed to

In this example strings are always copied from the CODE area into an XDATA buffer. By customizing the library function "strcpy()" to use a CODE source pointer and a XDATA destination pointer, the runtime for the string copy was reduced by 50%. The new strcpy has been named strcpy_x_c().

The function prototype is:

extern char xdata *strcpy(char xdata*,char code *) ;

Here is the code produced by the spaced pointer strcpy():

; char xdata *strcpy_x_c(char xdata *s1, char code *s2) {
_strcpy_x_c:
MOV s2?10,R4
MOV s2?10+01H,R5
;__ Variable 's1?10' assigned to Register 'R6/R7' __
; unsigned char i = 0;
;__ Variable 'i?11' assigned to Register 'R1' __
CLR A
MOV R1,A
?C0004:
;
; while ((s1[i++] = *s2++) != 0);
INC s2?10+01H
MOV A,s2?10+01H
MOV R4,s2?10
JNZ ?C0008
INC s2?10
?C0008:
DEC A
MOV DPL,A
MOV DPH,R4
CLR A
MOVC A,@A+DPTR
MOV R5,A
MOV R4,AR1
INC R1
MOV A,R7
ADD A,R4
MOV DPL,A
CLR A
ADDC A,R6
MOV DPH,A
MOV A,R5
MOVX @DPTR,A
JNZ ?C0004
?C0005:
; return (s1);
; }
?C0006:
END

Notice that no library functions are used to determine which memory spaces are intended. The function prototype tells C51 only to look in code for the string and xdata for the RAM buffer.

Pointers and Arrays | Structures and Unions | Generic and Spaced Pointers ]

ESAcademy, 2000

All materials
provided 'as is'
see Disclaimer

www.esacademy.com
info@esacademy.com