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 Reply Children
  • 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?