This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

function pointers in Dallas 390 contiguous mode

I was struggling with the function pointer in Dallas 390 contiguous mode. It seems that the linker might not relocate the correct address in function pointer. Check the following code:


void Test(void)
{
    UINT32 u32Tmp;

    u32Tmp = 0x12345678ul;
    TASK_PRN(("u32Func = %lx\n", u32Tmp));
    u32Tmp = Test;
    TASK_PRN(("u32Func = %lx\n", u32Tmp));
}

The Linker generate the address for Test: Test function is located at 2D90EH. 02D90EH 02D957H 00004AH BYTE INSEG ECODE ?PR?TEST?TASK The TASK_PRN macro calls my own written printf utility. Here is the output: u32Func = 12345678 u32Func = 83d90e I couldn't figure out why is this happening. Keil C version : C Compiler : C51.Exe V7.20 Assembler: AX51.Exe V2.13 Linker/Locator: LX51.Exe V3.64 Librian: LIBX51.Exe V4.24 C compiler Setting: LARGE OMF2 ROM(D16M) OPTIMIZE (SIZE) BROWSE ORDER MODDP2 Any body encounter this problem ? Thanks in advance! Lucas

  • Linker Bug confirmed
    I've checked the assembly listing and the generated binary code. And I found that the linker does not give correct relocation address in instruction relocation record.
    assembly listing

                 ; FUNCTION Test (BEGIN)
    ; SOURCE LINE # 246
    ; SOURCE LINE # 247
    ; SOURCE LINE # 250
    0000 7F78              MOV     R7,#078H
    0002 7E56              MOV     R6,#056H
    0004 7D34              MOV     R5,#034H
    0006 7C12              MOV     R4,#012H
    ;---- Variable 'u32Tmp' assigned to Register 'R4/R5/R6/R7' ----
    ; SOURCE LINE # 251
    0008 7B00        R     MOV     R3,#MBYTE ?SC_117
    000A 7A00        R     MOV     R2,#HIGH ?SC_117
    000C 7900        R     MOV     R1,#LOW ?SC_117
    000E 90000000    E     MOV     DPTR,#?UART_iPrintk?BYTE
    0012 12000000    E     LCALL   ?C?PSTXDATA
    0016 90000000    E     MOV     DPTR,#?UART_iPrintk?BYTE+03H
    001A 12000000    E     LCALL   ?C?LSTXDATA
    001E 12000000    E     LCALL   UART_iPrintk
                                               ; SOURCE LINE # 252
    0022 7B00        R     MOV     R3,#MBYTE Test
    0024 7A00        R     MOV     R2,#HIGH Test
    0026 7900        R     MOV     R1,#LOW Test
    0028 AF01              MOV     R7,AR1
    002A AE02              MOV     R6,AR2
    002C AD03              MOV     R5,AR3
    002E 7C00              MOV     R4,#00H
    
    Binary Code
    1D90E: 7F 78       ; MOV R7 , #078H
    1D910: 7E 56       ; MOV R6, #056H
    ....
    1D930: 7B 83       ; MOV R3, #083H
    1D932: 7A D9       ; MOV R2, #0D9H
    1D934: 79 0E       ; MOV R1, #00EH
    

    That's why I get the strange results:
    32Func = 12345678
    u32Func = 83d90e
    

  • Be sure to also report this direct to Keil support!

  • The bug is in your expectations, not in the linker. What on earth made you assume you knew what the result of casting a pointer to an integer was, better than the tools that actually use those pointers? Do you know what terms like "undefined behaviour" or "unspecified result" mean?

    Not only is your expectation unfounded, it actually contradicts the documented behaviour, too.

  • Refer to the following KB article: http://www.keil.com/support/docs/2226.htm

    And to the description for far pointers in the C51 Manual: http://www.keil.com/support/man/docs/c51/c51_le_far.htm

    Based on this information and the address of your function (2D90EH), I would conclude that the far pointer to the function should contain 0x83D90E.

    Jon

  • Linker Bug confirmed

    No. You need to read the section in the Cx51 Compiler User's Guide about Language Extensions->Memory Types->Far. It contains the description of how "far" memory pointers are mapped on Dallas devices.