Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
50
Добавлен:
14.04.2015
Размер:
1.37 Mб
Скачать

Keil Software — Cx51 Compiler User’s Guide

111

 

 

Pointer Conversions

The Cx51 compiler may convert between memory-specific pointers and generic pointers. Pointer conversions can be forced by explicit program code using type casts or can be coerced by the compiler implicitly.

The Cx51 compiler converts a memory-specific pointer into a generic pointer when the memory-specific pointer is passed as an argument to a function which requires a generic pointer. This is the case for functions such as printf, sprintf, and gets which use generic pointers as arguments. For example:

extern int printf (void

*format, ...);

3

extern int myfunc (void code *p, int xdata *pq);

int xdata *px;

 

 

char code *fmt

= "value = %d | %04XH\n";

 

 

void debug_print (void) { printf (fmt, *px, *px); myfunc (fmt, px);

}

/* fmt is converted */ /* no conversions */

In the call to printf, the argument fmt which represents a 2-byte code pointer is automatically converted or coerced into a 3-byte generic pointer. This is done because the prototype for printf requires a generic pointer as the first argument.

NOTE

A memory-specific pointer used as an argument to a function is always converted into a generic pointer if no function prototype is present. This can cause errors if the called function actually expects a shorter pointer as an argument. Avoid these kinds of errors in programs by using #include files and prototype all external functions. This guarantees conversion of the necessary types by the compiler and ensures that the compiler detects type conversion errors.

112 Chapter 3. Language Extensions

The following table details the process involved in converting generic pointers (generic *) to memory-specific pointers (code *, xdata *, idata *, data *, pdata *).

 

 

Conversion Type

Description

 

 

 

generic * to code *

The offset section (2 bytes) of the generic pointer is used.

 

 

 

generic * to xdata *

The offset section (2 bytes) of the generic pointer is used.

 

 

 

generic * to data *

The low-order byte of the generic pointer offset is used.

 

 

 

 

The high-order byte is discarded.

 

 

 

generic * to idata *

The low-order byte of the generic pointer offset is used.

 

 

 

 

The high-order byte is discarded.

 

3

 

generic * to pdata *

The low-order byte of the generic pointer offset is used.

 

 

 

The high-order byte is discarded.

 

 

The following table describes the process involved in converting

 

 

 

memory-specific pointers (code *, xdata *, idata *, data *, pdata *) to generic

 

 

 

 

 

pointers (generic *).

 

 

 

 

 

 

 

 

 

Conversion Type

Description

 

 

 

code * to generic *

The memory type of the generic pointer is set to 0xFF for code.

 

 

 

 

The 2-byte offset of the code * is used.

 

 

 

xdata * to generic *

The memory type of the generic pointer is set to 0x01 for xdata.

 

 

 

 

The 2-byte offset of the xdata * is used.

 

 

 

data * to generic *

The 1-byte offset of the idata * / data * is converted to an unsigned

 

 

 

 

int and used as the offset.

 

 

 

idata * to generic *

The memory type of the generic pointer is set to 0x00 for idata / data.

 

 

 

pdata * to generic *

The memory type of the generic pointer is set to 0xFE for pdata.

 

 

 

 

The 1-byte offset of the pdata * is converted to an unsigned int and

 

 

 

 

used as the offset.

 

 

 

 

 

 

Keil Software — Cx51 Compiler User’s Guide

113

 

 

The following listing illustrates a few pointer conversions and the resulting code:

stmt level

source

 

 

 

1

 

int *p1;

/* generic ptr (3 bytes) */

 

2

 

int xdata *p2;

/* xdata ptr (2 bytes) */

 

3

 

int idata *p3;

/* idata ptr (1 byte) */

 

4

 

int code *p4;

/* code ptr (2 bytes */

 

5

 

 

 

 

 

 

6

 

void pconvert (void) {

 

 

7

1

p1

= p2;

/* xdata* to generic* */

 

8

1

p1

= p3;

/* idata* to generic* */

 

9

1

p1

= p4;

/* code*

to generic* */

 

10

1

 

 

 

 

 

11

1

p4

= p1;

/* generic* to code* */

 

12

1

p3

= p1;

/* generic* to idata* */

 

13

1

p2

= p1;

/* generic* to xdata* */

 

3

14

1

 

 

 

 

15

1

p2

= p3;

/* idata* to xdata* (WARN) */

*** WARNING

259 IN LINE 15 OF P.C: pointer: different mspace

16

1

p3

= p4;

/* code*

to idata* (WARN) */

*** WARNING

259 IN LINE 16 OF P.C: pointer: different mspace

 

17

1

}

 

 

 

 

ASSEMBLY LISTING OF GENERATED OBJECT CODE

;FUNCTION pconvert (BEGIN)

;SOURCE LINE # 7

0000

750001 R

MOV

p1,#01H

0003

850000 R

MOV

p1+01H,p2

0006

850000 R

MOV

p1+02H,p2+01H

 

 

 

 

; SOURCE LINE # 8

0009

750000 R

MOV

p1,#00H

000C

750000 R

MOV

p1+01H,#00H

000F

850000 R

MOV

p1+02H,p3

 

 

 

 

; SOURCE LINE # 9

0012

7B05

 

MOV

R3,#0FFH

0014

AA00

R

MOV

R2,p4

0016

A900

R

MOV

R1,p4+01H

0018

8B00

R

MOV

p1,R3

001A

8A00

R

MOV

p1+01H,R2

001C

8900

R

MOV

p1+02H,R1

 

 

 

 

; SOURCE LINE # 11

001E

AE02

 

MOV

R6,AR2

0020

AF01

 

MOV

R7,AR1

0022

8E00

R

MOV

p4,R6

0024

8F00

R

MOV

p4+01H,R7

 

 

 

 

; SOURCE LINE # 12

0026

AF01

 

MOV

R7,AR1

0028

8F00

R

MOV

p3,R7

 

 

 

 

; SOURCE LINE # 13

002A

AE02

 

MOV

R6,AR2

002C

8E00

R

MOV

p2,R6

002E

8F00

R

MOV

p2+01H,R7

 

 

 

 

; SOURCE LINE # 15

0030

750000 R

MOV

p2,#00H

0033

8F00

R

MOV

p2+01H,R7

 

 

 

 

; SOURCE LINE # 16

0035

850000 R

MOV

p3,p4+01H

 

 

 

 

; SOURCE LINE # 17

0038

22

 

RET

 

 

; FUNCTION pconvert (END)

114

Chapter 3. Language Extensions

 

 

Abstract Pointers

Abstract pointer types access fixed memory locations in any memory area. You may also use abstract pointers to call functions located at absolute or fixed addresses.

Abstract pointer types are described here using code examples with the following variables.

char xdata *px;

/* ptr to xdata */

char idata *pi;

/* ptr to idata */

char code *pc;

/* ptr to code */

3

 

char c;

 

 

/* char variable in data space */

 

 

 

 

 

 

 

 

int i;

 

 

/* int variable in data space */

 

 

 

The following example assigns the address of the main C function to a pointer

 

 

 

 

 

 

(stored in data memory) to a char stored in code memory.

 

 

 

 

 

 

 

 

 

 

 

 

Source

 

 

pc = (void *) main;

 

 

 

 

 

Object

 

 

0000 750000

R

MOV

pc,#HIGH main

 

 

 

 

 

 

0003 750000

R

MOV

pc+01H,#LOW main

 

 

 

 

 

 

 

 

 

 

 

The following example casts the address of the variable i (which is an

int data *) to a pointer to a char in idata. Since i is stored in data and since indirectly accessed data is idata, this pointer conversion is valid.

Source

pi =

(char idata *) &i;

 

Object

0000

750000 R

MOV

pi,#LOW i

 

 

 

 

 

The following example casts a pointer to a char in xdata to a pointer to a char in idata. Since xdata pointers occupy 2 bytes and idata pointers occupy 1 byte, this pointer conversion may not yield the desired results since the upper byte of the xdata pointer is ignored. Refer to “Pointer Conversions” on page 111 for more information about converting between different pointer types.

Source

pi =

(char idata *) px;

 

Object

0000

850000 R

MOV

pi,px+01H

The following example casts 0x1234 as a pointer to a char in code memory.

Source

pc = (char code *) 0x1234;

 

Object

0000 750012

R

MOV

pc,#012H

 

0003 750034

R

MOV

pc+01H,#034H

 

 

 

 

 

Keil Software — Cx51 Compiler User’s Guide

115

 

 

The following example casts 0xFF00 as a function pointer that takes no arguments and returns an int, invokes the function, and assigns the return value to the variable i. The portion of this example that performs the function pointer type cast is: ((int (code *)(void)) 0xFF00). By adding the argument list to the end of the function pointer, the compiler can correctly invoke the function.

Source

i = ((int (code *)(void)) 0xFF00) ();

Object

0000

12FF00

 

LCALL

0FF00H

 

0003

8E00

R

MOV

i,R6

 

0005

8F00

R

MOV

i+01H,R7

 

 

 

 

 

 

The following example casts 0x8000 as a pointer to a char in code memory, extracts the char pointed to, and assigns it to the variable c.

Source

c = *((char code *) 0x8000);

3

Object

0000 908000

 

MOV

DPTR,#08000H

 

0003

E4

 

CLR

A

 

 

0004

93

 

MOVC

A,@A+DPTR

 

 

0005

F500

R

MOV

c,A

 

The following example casts 0xFF00 as a pointer to a char in xdata memory,

 

extracts the char pointed to, and adds it to the variable c.

 

 

 

 

Source

c += *((char xdata *) 0xFF00);

 

Object

0000 90FF00

 

MOV

DPTR,#0FF00H

 

 

0003

E0

 

MOVX

A,@DPTR

 

 

0004

2500

R

ADD

A,c

 

 

0006

F500

R

MOV

c,A

 

 

 

 

 

 

 

 

The following example casts 0xF0 as a pointer to a char in idata memory, extracts the char pointed to, and adds it to the variable c.

Source c += *((char idata *) 0xF0);

Object

0000

78F0

 

MOV

R0,#0F0H

 

0002

E6

 

MOV

A,@R0

 

0003

2500

R

ADD

A,c

 

0005

F500

R

MOV

c,A

 

 

 

 

 

 

116 Chapter 3. Language Extensions

The following example casts 0xE8 as a pointer to a char in pdata memory, extracts the char pointed to, and adds it to the variable c.

Source

c += *((char pdata

*) 0xE8);

Object

0000

78E8

 

MOV

R0,#0E8H

 

0002

E2

 

MOVX

A,@R0

 

0003

2500

R

ADD

A,c

 

0005

F500

R

MOV

c,A

 

 

 

 

 

 

The following example casts 0x2100 as a pointer to an int in code memory, extracts the int pointed to, and assigns it to the variable i.

 

 

Source

i = *((int code *) 0x2100);

 

3

 

 

Object

0000 902100

 

MOV

DPTR,#02100H

 

 

0003

E4

 

CLR

A

 

 

0004

93

 

MOVC

A,@A+DPTR

 

 

0005

FE

 

MOV

R6,A

 

 

 

0006

7401

 

MOV

A,#01H

 

 

 

0008

93

 

MOVC

A,@A+DPTR

 

 

 

0009

8E00

R

MOV

i,R6

 

 

 

000B

F500

R

MOV

i+01H,A

 

 

 

 

 

 

 

 

The following example casts 0x4000 as a pointer to a pointer in xdata that points to a char in xdata. The assignment extracts the pointer stored in xdata that points to the char which is also stored in xdata.

Source

px = *((char xdata

* xdata

*) 0x4000);

Object

0000 904000

 

MOV

DPTR,#04000H

 

0003

E0

 

MOVX

A,@DPTR

 

0004

FE

 

MOV

R6,A

 

0005

A3

 

INC

DPTR

 

0006

E0

 

MOVX

A,@DPTR

 

0007

8E00

R

MOV

px,R6

 

0009

F500

R

MOV

px+01H,A

 

 

 

 

 

 

Keil Software — Cx51 Compiler User’s Guide

117

 

 

Like the previous example, this example casts 0x4000 as a pointer to a pointer in xdata that points to a char in xdata. However, the pointer is accessed as an array of pointers in xdata. The assignment accesses array element 0 (which is stored at 0x4000 in xdata) and extracts the pointer there that points to the char stored in xdata.

Source

px = ((char xdata * xdata *) 0x4000) [0];

Object

0000 904000

 

MOV

DPTR,#04000H

 

0003

E0

 

MOVX

A,@DPTR

 

0004

FE

 

MOV

R6,A

 

0005

A3

 

INC

DPTR

 

0006

E0

 

MOVX

A,@DPTR

 

0007

8E00

R

MOV

px,R6

 

0009

F500

R

MOV

px+01H,A

 

 

 

 

 

 

The following example is identical to the previous one except that the

3

assignment accesses element 1 from the array. Since the object pointed to is a

 

pointer in xdata (to a char), the size of each element in the array is 2 bytes. The

 

assignment accesses array element 1 (which is stored at 0x4002 in xdata) and

 

extracts the pointer there that points to the char stored in xdata.

 

 

 

 

Source

px = ((char xdata * xdata *) 0x4000) [1];

 

Object

0000 904002

 

MOV

DPTR,#04002H

 

 

0003

E0

 

MOVX

A,@DPTR

 

 

0004

FE

 

MOV

R6,A

 

 

0005

A3

 

INC

DPTR

 

 

0006

E0

 

MOVX

A,@DPTR

 

 

0007

8E00

R

MOV

px,R6

 

 

0009

F500

R

MOV

px+01H,A

 

 

 

 

 

 

 

 

Соседние файлы в папке HLP