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

assembler rtn called from C

I have the impression that an assembler non-interrupt subroutine called from 'C' need save no registers.

Is that correct?

Erik

Parents
  • When C makes a call to a function written in assembler, the C optimiser generally has to assume the worst case - that any of the registers may be overwritten by the assembly language function.

    However, using the REGUSE control in the assembly language function will inform the optimiser about exactly which registers are changed by the function - this allows global register optimisation to be applied.

    In the REGUSE control, you only have to specify those registers that are actually modified by the function. In order to optimise performance, you may choose to save and restore some (or all) of the registers that you use.

    If you are keen to optimise performance, you will need to do some investigation. In general, it is the registers R0 to R7 that are critical. The optimiser may alocate these registers to automatic variables in the calling C function - that are the most important. This optimisation can be very significant to performance so it may be important to ensure that the optimiser can apply it effectivly.

Reply
  • When C makes a call to a function written in assembler, the C optimiser generally has to assume the worst case - that any of the registers may be overwritten by the assembly language function.

    However, using the REGUSE control in the assembly language function will inform the optimiser about exactly which registers are changed by the function - this allows global register optimisation to be applied.

    In the REGUSE control, you only have to specify those registers that are actually modified by the function. In order to optimise performance, you may choose to save and restore some (or all) of the registers that you use.

    If you are keen to optimise performance, you will need to do some investigation. In general, it is the registers R0 to R7 that are critical. The optimiser may alocate these registers to automatic variables in the calling C function - that are the most important. This optimisation can be very significant to performance so it may be important to ensure that the optimiser can apply it effectivly.

Children
  • Thanks Dan, Andy & Graham.

    Michael, I was not asking about assembler code, but about the 'C' compiler.

    y'all have fun now, ya hear

    Erik

  • The point is the REGUSE control in the assembly code makes a big difference in the C code that calls the assembly code!!

    In the following example the calling C code was reduced by almost 1/2 in size by using REGUSE on the assembly side.

    Main.c
    
    void WithoutRegUse( char C );
    void WithRegUse( char C );
    
    void CallWithoutRegUse( void )
    {
      char i;
      char xdata* p = 0;
      for( i = 0; i != 0x12; ++i, ++p )
        WithoutRegUse(*p);
    }
    
    void CallWithRegUse( void )
    {
      char i;
      char xdata* p = 0;
      for( i = 0; i != 0x12; ++i, ++p )
        WithRegUse(*p);
    }
    
    void main( void )
    {
      CallWithoutRegUse();
      CallWithRegUse();
    }
    Sub.c
    
    #include <reg52.h>
    
    volatile V;
    
    void WithoutRegUse( char C )
    {
      ACC = C;
      #pragma asm
        swap a
        mov  V,a
      #pragma endasm
      return;
    }
    
    #pragma asm
      $reguse _WithRegUse( A, R7 ) 
    #pragma endasm
    void WithRegUse( char C )
    {
      ACC = C;
      #pragma asm
        swap a
        mov  V,a
      #pragma endasm
      return;
    }
    

    Partial Main.lst
    
                 ; FUNCTION CallWithoutRegUse (BEGIN)
                                               ; SOURCE LINE # 7
                                               ; SOURCE LINE # 8
                                               ; SOURCE LINE # 10
    0000 E4                CLR     A
    0001 F500        R     MOV     p,A
    0003 F500        R     MOV     p+01H,A
                                               ; SOURCE LINE # 11
    0005 F500        R     MOV     i,A
    0007         ?C0001:
    0007 E500        R     MOV     A,i
    0009 6412              XRL     A,#012H
    000B 6017              JZ      ?C0004
                                               ; SOURCE LINE # 12
    000D 850082      R     MOV     DPL,p+01H
    0010 850083      R     MOV     DPH,p
    0013 E0                MOVX    A,@DPTR
    0014 FF                MOV     R7,A
    0015 120000      E     LCALL   _WithoutRegUse
    0018 0500        R     INC     i
    001A 0500        R     INC     p+01H
    001C E500        R     MOV     A,p+01H
    001E 70E7              JNZ     ?C0001
    0020 0500        R     INC     p
    0022         ?C0010:
    0022 80E3              SJMP    ?C0001
                                               ; SOURCE LINE # 13
    0024         ?C0004:
    0024 22                RET     
                 ; FUNCTION CallWithoutRegUse (END)
    
                 ; FUNCTION CallWithRegUse (BEGIN)
                                               ; SOURCE LINE # 15
                                               ; SOURCE LINE # 16
                                               ; SOURCE LINE # 18
    ;---- Variable 'p' assigned to Register 'DPTR' ----
    0000 900000            MOV     DPTR,#00H
                                               ; SOURCE LINE # 19
    ;---- Variable 'i' assigned to Register 'R6' ----
    0003 E4                CLR     A
    0004 FE                MOV     R6,A
    0005         ?C0005:
    0005 EE                MOV     A,R6
    0006 6412              XRL     A,#012H
    0008 6009              JZ      ?C0008
                                               ; SOURCE LINE # 20
    000A E0                MOVX    A,@DPTR
    000B FF                MOV     R7,A
    000C 120000      E     LCALL   _WithRegUse
    000F 0E                INC     R6
    0010 A3                INC     DPTR
    0011 80F2              SJMP    ?C0005
                                               ; SOURCE LINE # 21
    0013         ?C0008:
    0013 22                RET     
                 ; FUNCTION CallWithRegUse (END)
    

  • Too right. Thanks for the nice examples.