Skip to main content
smart
Associate III
March 8, 2008
Question

Jumping execution to an absolute address

  • March 8, 2008
  • 6 replies
  • 3434 views
Posted on March 08, 2008 at 05:12

Jumping execution to an absolute address

    This topic has been closed for replies.

    6 replies

    troy
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:25

    Try This, I haven't tried this but I think it will work

    typedef void (*appFunc)(void);

    void main(void)

    {

    appFunc appFuncAddr;

    … some other code

    appFuncAddr = (appFunc )0x8006C00;

    appFuncAddr)();

    }

    Troy

    smart
    smartAuthor
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 12:25

    I want to write a code to jump at an absolute location.

    I used this code I always get hard fault exception

    I have already defined some code at 0x8006C00.

    typedef void (*appFunc)(void);

    void main(void)

    {

    u32 appFuncAddr;

    … some other code

    appFuncAddr = (u32)0x8006C00;

    ((appFunc)appFuncAddr)();

    }

    smart
    smartAuthor
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 12:25

    Thanks Eric,

    with your suggestions code is working.

    Thanks a lot!!

    ericvanolden9
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 12:25

    If you want to jump at address 0x8006C00, you must write

    appFuncAddr = (appFunc )0x8006C01;

    Some explanations :

    Remember that previous ARM processors have two sets of instructions : ARM and Thumb. To go from one set to other a BX instruction is use with the form of BX Rx. If bit 0 of Rx is 0, next is ARM instructions, if bit 1 of Rx is 1, next is Thumb instructions.

    With Cortex-M3, there is no ARM instructions but only Thumb with Thumb2 extensions. But BX instructions is the same. If you try to go to ARM instructions you obtain an Hard Fault Exception.

    When you write :

    appFuncAddr = (appFunc )0x8006C00;

    appFuncAddr)();

    compiler generate

    LDR Rx,=0x8006C00

    BX Rx

    So bit 0 is 0 and you try to go to ARM instructions.

    If your code is at 0x8006C00, you must have in assembleur :

    LDR Rx,=0x8006C01

    BX Rx

    So processor jump at address 0x8006C00 in Thumb mode (bit 0 is 1)

    gdp123a
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 12:25

    Thanks Eric, your clear explanation has helped me understand a problem I was having with my assembler routine.

    I'm new to ARM processors and this mode swapping scheme (called ''interworking'') took me by surprise. This was causing me trouble when trying to calculate the address into a jump table.

    I now understand that with the IAR assembler, all labels in code space have bit0 = 1 (because they are thumb code labels).

    So the following will work:

    ADR Rx, =Label ;where label is in code space, bit 1 is set

    BX Rx

    but the following won't work (this is what I was doing wrong):

    ADR Rx, =Label

    MOV PC, Rx ;FAIL - will try and jump to odd address

    The ''MOV PC, Rx'' isn't an interworking instruction (it doesn't consider bit0 as special), so it tries to jump to an odd address - causing an exception.

    Some assemblers apparently don't set bit0 on labels, so I will be using the following code to ensure portability:

    ADR Rx, Start_of_jump_table

    BIC Rx, Rx, #1 ;clear that tricky interworking bit

    ADD Rx, Rx, Ry ;add any jump table offset here

    MOV PC, Rx ;jump into the table

    So the following might work for Troy as well:

    LDR Rx,=0x8006C00

    MOV PC, Rx

    Greg.

    ericvanolden9
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 12:25

    With IAR assembler, bit 0 is set for label in code section (keyword 'thumb') but is reset in data section (keyword 'data').

    When you declare a jump table with directive 'dc8', 'dc16' or 'dc32', you are generally in data section and so label for start of jump table don't have bit 0 set.