|
|
|||||||||
Generic PointersC51 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:
Spaced Pointers In C51Considerable 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: to produce an uncommitted pointer into the XDATA space or 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:
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) { 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 |