Absolute address of a function in Microchip XC16

Tag: compiler , function-pointers , pic , microchip , xc16 Author: xuyang520520 Date: 2013-01-17

Device: dsPIC33FJ128GP802

I have some *.s files as follows

.global _D1
.section .speex, code
.pword 0x66C821,  0x1B0090,  0xD96C36,  0x9B60B0,  0xDD4E36,  0xBF4E53
.pword 0xD1098B,  0x719BD9,  0x873989,  0x003B69,  0x279035,  0xED4244
.pword 0xE1403C,  0x54D439,  0x826550,  0xC59627,  0xDD0432,  0x88FA29

I have declared the same in a *.h

extern void D1(void);

Now I am passing the D1 to a table read function

nowPlaying.file1 = (unsigned long) D1;

My problem is that, if the address of D1 is above 0x8000, the routine is not correct. I tried large and small code models, but the result is the same. I think this is due to the 16-bit limitation of the pointers. Is there any method to access the absolute address of D1 directly from the code. Maybe something like a built-in function or macros.

Please note that the compiler manual says:

The MPLAB XC16 C Compiler fully supports pointers to functions, which allows functions to be called indirectly. Function pointers are always 16 bits wide.

I have posted the same question at


Please clarify, as you have been asked several times, whether the stuff in the .s file is really code or data; please define 'the function is not correct'; and please continue the whole conversation here rather than back at electronics.stackexchange.com where it came from. Otherwise I cannot see the point of you posting here at all.

Other Answer1

As I wrote at electronics.stackexchange.com, you are basically lying to the compiler about D1, by casting that to unsigned long, when it isn't an unsigned long at all. This is very likely to cause problems down the track.

If the stuff starting at D1 is code that can conforms to the C calling conventions, D1 should be declared as extern void D1(void), and all the struct members and variables and parameters that take its address should be declared as void (*D1)(void), and you can call it via those values with the syntax (*var)(). I don't know what the nowPlaying.file1 variable is for: you could also just call function(D1) if function() is declared properly, i.e. as above.

If it is data, it should be const short D1[], and you don't need the assembler: you can provide the values in C as const short D1[] = {...};. The compiler should put D1 into the code segment as it is const.


@downvoter Please explain. Tell us why a function pointer shouldn't be typed using the syntax provided for the purpose, and why it is superior to cast it to an unsigned long and back.