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

PUSH and POP in Keil C

dear all, how can I use PUSH and POP instruction in Keil C ?
Thanks

Parents
  • The only way to do this just in C is to create a pseudo stack (an array) and a pseudo pointer. Simply write your own pseudo_push() and pseudo_pop() functions.

    There is a relatively safe way to do this using 8051 assembly language functions that can be called from a C51 function. You will need something like this:

    #pragma ASM
    
        $REGUSE _push_byte( A, DPH, DPL )
    
    #pragma ENDASM
    
    void push_byte( char x )
    {                               //
        x = x;                      // Supress UNUSED warning.
                                    //
        #pragma ASM
    
            POP     DPH             ;Get return address from stack
            POP     DPL             ;and store in DPTR
            MOV     A,R7            ;Get x into accumulator...
            PUSH    Acc             ;...and push it onto the stack.
            CLR     A               ;
            JMP     @A+DPTR         ;Return to caller.
    
        #pragma ENDASM
    }
    
    #pragma ASM
    
        $REGUSE _pop_byte( A, DPH, DPL, R7 )
    
    #pragma ENDASM
    
    char pop_byte( void )
    {                               //
                                    //
        #pragma ASM
    
            POP     DPH             ;Get return address from stack
            POP     DPL             ;and store in DPTR
            POP     Acc             ;Get the return value from stach
            MOV     R7,A            ;and put it in R7.
            CLR     A               ;
            JMP     @A+DPTR         ;Return to caller.
    
        #pragma ENDASM
    
        return(0);                  // Dummy return.
    }
    
    And use it like this:
    
    void push_byte( char x );
    char pop_byte( void );
    
    void main( void )
    {
        unsigned char loop;
        char          a;
        char          b;
    
        a = 0;
    
        loop = 255;
    
        do
        {
            push_byte( a );
            b = pop_byte();
            a++;
        }while( --loop != 0 );
    
        loop = 255;
    }
    
    This is much safer than placing pushes and pops directly in-line because the compiler expects a function call to disrupt register values etc.

    From my C51 experience, my guess is that this will work fairly reliably. But, and its a big BUT, there are no garantees. Even if it works for now, it could stop working at the next compiler update!

    Anyway, why do you want to do this?

Reply
  • The only way to do this just in C is to create a pseudo stack (an array) and a pseudo pointer. Simply write your own pseudo_push() and pseudo_pop() functions.

    There is a relatively safe way to do this using 8051 assembly language functions that can be called from a C51 function. You will need something like this:

    #pragma ASM
    
        $REGUSE _push_byte( A, DPH, DPL )
    
    #pragma ENDASM
    
    void push_byte( char x )
    {                               //
        x = x;                      // Supress UNUSED warning.
                                    //
        #pragma ASM
    
            POP     DPH             ;Get return address from stack
            POP     DPL             ;and store in DPTR
            MOV     A,R7            ;Get x into accumulator...
            PUSH    Acc             ;...and push it onto the stack.
            CLR     A               ;
            JMP     @A+DPTR         ;Return to caller.
    
        #pragma ENDASM
    }
    
    #pragma ASM
    
        $REGUSE _pop_byte( A, DPH, DPL, R7 )
    
    #pragma ENDASM
    
    char pop_byte( void )
    {                               //
                                    //
        #pragma ASM
    
            POP     DPH             ;Get return address from stack
            POP     DPL             ;and store in DPTR
            POP     Acc             ;Get the return value from stach
            MOV     R7,A            ;and put it in R7.
            CLR     A               ;
            JMP     @A+DPTR         ;Return to caller.
    
        #pragma ENDASM
    
        return(0);                  // Dummy return.
    }
    
    And use it like this:
    
    void push_byte( char x );
    char pop_byte( void );
    
    void main( void )
    {
        unsigned char loop;
        char          a;
        char          b;
    
        a = 0;
    
        loop = 255;
    
        do
        {
            push_byte( a );
            b = pop_byte();
            a++;
        }while( --loop != 0 );
    
        loop = 255;
    }
    
    This is much safer than placing pushes and pops directly in-line because the compiler expects a function call to disrupt register values etc.

    From my C51 experience, my guess is that this will work fairly reliably. But, and its a big BUT, there are no garantees. Even if it works for now, it could stop working at the next compiler update!

    Anyway, why do you want to do this?

Children
No data