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

Necessary to save used registers in assembly ?

I am using assembly language routines
called from C code.
Within the assembly routines, is it necessary to save the registers used?

Ex:
MY_ASM_ROUTINE:
PUSH ACC ; necessary ?
CLR A ; overwrite ACC
POP ACC
RET

main(){
MY_ASM_ROUTINE();
}

Or does the C compiler assume that
registers can be overwritten by
calls to routines?

I couldn't find the answer in the manuals.

Thanks in advance
Jim Burke

Parents
  • Hi Jim,

    I found these documents
    http://www.keil.com/support/docs/939.htm
    http://www.keil.com/support/docs/904.htm
    They tell about REGFILE directives, but both apply to C51 v5.5 and I don't know if they can hel you.

    I understand that REGFILE directives are
    to be used in:
    1. Assembly code (to specify which register are used in each function)
    2. In C compiling parameters (to tell the compiler to optimize register usage following information retrieved in 1.)
    3. In BL51 compiling parameters (why ??)

    I think that if you don't use REGFILE directives C51 compiler assumes that *all* register are corrupted in the Assembly routine, so it "disables" the 'Register variables optimization'.

    Try to analyze the Assembly file created by C51, so you can understand how it uses register to store variables
    first and after Assembly-routine callings. (If C51 v4.10 doesn't allow to create SRC file from C modules use a debugger or a disassembler)

    Tomorrow (in Italy is already 8:00 PM), I hope to make some test.

    Marcello

Reply
  • Hi Jim,

    I found these documents
    http://www.keil.com/support/docs/939.htm
    http://www.keil.com/support/docs/904.htm
    They tell about REGFILE directives, but both apply to C51 v5.5 and I don't know if they can hel you.

    I understand that REGFILE directives are
    to be used in:
    1. Assembly code (to specify which register are used in each function)
    2. In C compiling parameters (to tell the compiler to optimize register usage following information retrieved in 1.)
    3. In BL51 compiling parameters (why ??)

    I think that if you don't use REGFILE directives C51 compiler assumes that *all* register are corrupted in the Assembly routine, so it "disables" the 'Register variables optimization'.

    Try to analyze the Assembly file created by C51, so you can understand how it uses register to store variables
    first and after Assembly-routine callings. (If C51 v4.10 doesn't allow to create SRC file from C modules use a debugger or a disassembler)

    Tomorrow (in Italy is already 8:00 PM), I hope to make some test.

    Marcello

Children
  • Here are a few things to consider:

    1. There is no difference between a C function and an assembly function.

    2. A called assembler function may use all registers A, B, R0-R7, and DPTR without saving and restoring them.

    3. It is ALWAYS the caller's responsibility to reload register contents after a function call.

    4. If an assembler function (called from C) takes arguments and/or returns values, it must use the same conventions as the C compiler. Refer to the manual.

    5. The regfile is used to perform global register optimizations. Basically, a bipmap of the registers used in each function is built up and used by the C compiler to optimize saving and restoring registers.

    Hope this helps.

    Jon

  • Thanks for the reply Jon.

    I can therefore assume that the compiler
    will restore registers after a call,
    even if it is optimizing performance by
    using registers. I do not need to
    save used registers in an assembly
    program ( an ISR is an exception ) since
    the caller will assume its registers may have been overwritten.

    Thanks again for your reply.
    It eliminated my doubt.

    Jim

  • >1. There is no difference between a C function and an assembly function.

    >5. The regfile is used to perform
    >global register optimizations.
    >Basically, a bipmap of the registers
    >used in each function is built up and
    >used by the C compiler to optimize >saving and restoring registers.

    I think you forget about $REGUSE directive.

    Sentence (1.) is not true.
    Main difference between C and Assembler functions is that C compiler don't know anything about using registers in assembler function.

    So, to force compiler apply 'global optimisation' under assembler functions user MUST explicitly declare used registers with $REGUSE directive.

    For example:
    --- file SWAPBYTE.C ---

    #pragma  SRC(SWAPBYTE.a51)
    
    
    #pragma asm
       $REGUSE _SwapByte(A, R7 )
    #pragma endasm
    
    uchar SwapByte(unsigned char Byte)
    {
      ACC = Byte;
    #pragma asm
      swap a
    #pragma endasm
      return( ACC );
    }
    



    P.S.
    Without $REGUSE compiler generate code for all callers of SwapByte() with reloading registers R0,R1,...,R6,DPTR,B.

    Adding lines:
    #pragma asm
       $REGUSE _SwapByte(A, R7 )
    #pragma endasm
    
    in my current project reduce code size
    from 44639 to 44489 bytes.