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

From C, inline assembly LJMP to Numerical Address

How do I perform a long jump to a numerical address from my C code?
I'm pretty sure I have to do this with inline assembly - however that
seems complicated for C51. I figured in C I could do this:

typedef void (*jmpPtr)(void);
jmpPtr jmp;

...

unsigned int address = 0x4000U;
jmp = (jmpPtr) address;
(*jmp)();

Except for the call differences, I think this would be the same as doing
a jump to the numerical address? Keil, is this correct?

Parents
  • I've tested the following code and verified that it works as advertised.<br>
    <br>

    unsigned address;
    
    void JumpedTo( void )
    {
        while (1)
            ;
    }
    
    void main( void )
    {
        unsigned char idata *p;
    
        /*  Set stack pointer to 0x7E, forcing the
         *  "pushed" address to straddle the data/idata
         *  boundary at 0x80.  NOTE: Only for 8052
         *  derivatives.
         */
        SP = 0x7E;
        address = JumpedTo;
    
        p = SP + 1;
        SP += 2;
        p[0] = address & 0xFF;
        p[1] = address >> 8;
        return;
    }
    <br>
    idata pointers and data pointers are equivalent, and in fact, have the "generic pointer" memory type. Declaring "p" as an idata pointer makes it more obvious (to me) that the pointer could access the full 256 byte range. I went ahead and tested with "p" declared as a "data *" also, just to be certain I'm not misleading anyone.<br>
    <br>
    --Dan Henry<br>

Reply
  • I've tested the following code and verified that it works as advertised.<br>
    <br>

    unsigned address;
    
    void JumpedTo( void )
    {
        while (1)
            ;
    }
    
    void main( void )
    {
        unsigned char idata *p;
    
        /*  Set stack pointer to 0x7E, forcing the
         *  "pushed" address to straddle the data/idata
         *  boundary at 0x80.  NOTE: Only for 8052
         *  derivatives.
         */
        SP = 0x7E;
        address = JumpedTo;
    
        p = SP + 1;
        SP += 2;
        p[0] = address & 0xFF;
        p[1] = address >> 8;
        return;
    }
    <br>
    idata pointers and data pointers are equivalent, and in fact, have the "generic pointer" memory type. Declaring "p" as an idata pointer makes it more obvious (to me) that the pointer could access the full 256 byte range. I went ahead and tested with "p" declared as a "data *" also, just to be certain I'm not misleading anyone.<br>
    <br>
    --Dan Henry<br>

Children
  • Let's try that again.

    Dan, you have inspired me. Here's my "Jump to an absolute address" that I hope solves the "jump from C" issue.

    // 'r_' prefix denotes a CPU 'r'egister.
    sfr r_stackPointer = 0x81;
    
    void main(void)
    {
        // Point so that this will work for 8051's and 52's.
        unsigned char data *p = 0x7E; 
    
        // Little endian, LSB in lower address, MSB in higher address.
        *p = 0x00;  // LSB of address 0x4000.
        ++p;
        *p = 0x40;  // MSB of address 0x4000;
    
        // Now fool the CPU (this is the magic part).
        r_stackPointer = 0x7F;
    
        // "Jump via return"
        return;
    }
    What fun.

    - Mark