[Back] [Top] [Next]

14 Assembler Interfacing To C Programs

The calling of assembler routines from C51 is not difficult, provided that you read both this and the user manual.

14.1 Assembler Function Example

The example below is taken from a real application where an EEPROM was being written in a page mode. Because of a 30us timeout of this mode, the 25us run time of the C51 code was viewed as being a bit marginal. It was therefore decided to code it in assembler.

If an assembler-coded function is to receive no parameters then an ordinary assembler label at the beginning of the function is simply called like any C function. Note that an extern function prototype must be given after the style of:

C51 File:

extern void asm_func(void).

A51 File:

ASM_FUNC:  MOV  A,#10   ; 8051 assembler instructions

Should there be parameters to be passed, C51 will place the first few parameters into registers. Exactly how it does this is outlined in section

The complication arises when there are more parameters to be passed than can be fitted into registers.

In this case the user must declare a memory area into which the extra parameters can be placed. Thus the assembler function must have a DATA segment defined that conforms to the naming conventions expected by C51.

In the example below, the segment

?DT?_WRITE_EE_PAGE?WRITE_EE SEGMENT DATA OVERLAYABLE

does just that.

The best advice is to write the C that calls the assembler and then compile with the SRC switch to produce an assemblable equivalent. Then look at what C51 does when it calls your as yet unwritten assembler function. If you stick to the parameter passing segment name generated by C51 you will have no problems.

Example Of Assembler Function With Many Parameters

C Calling Function

Within the C program that calls this function the following lines must be added to the calling module/source file:


   /* external reference to assembler routine */
  
extern unsigned char write_ee_page(char*,unsigned 
                          char,unsigned char) ;
  .
   dummy()
  .  {
     unsigned char number, eeprom_page_buffer, 
          ee_page_length ; 
     char * current_ee_page ;
  .
     number = write_ee_page (current_ee_page, 
          eeprom_page_buffer, ee_page_length) ;
  .  } /* End dummy */


The assembler routine is:


    NAME EEPROM_WRITE ;      
    
    PUBLIC  _WRITE_EE_PAGE              ; Essential!
    PUBLIC  ?_WRITE_EE_PAGE?END_ADDRESS ;
    PUBLIC  ?_WRITE_EE_PAGE?END_BUFFER  ;
; 
P6     EQU  0FAH  ; 
Port 6 has watchdog pin ; 
;**************************************************************************** 
;*<<<<<<<<< Declare CODE And DATA Segments For
           Assembler Routine >>>>>>>>>>>* 
;****************************************************************************; 
?PR?_WRITE_EE_PAGE?WRITE_EE SEGMENT CODE
?DT?_WRITE_EE_PAGE?WRITE_EE SEGMENT DATA OVERLAYABLE ; 
; 
;**************************************************************************** 
;*<<<<<< Declare Memory Area In Internal RAM For Local 
       Variables Etc. >>>>>>* 
;**************************************************************************** 
;
        RSEG ?DT?_WRITE_EE_PAGE?WRITE;
?_WRITE_EE_PAGE?END_ADDRESS:  DS   2   ;
?_WRITE_EE_PAGE?END_BUFFER:   DS   1   ;
;
;
;*******************************************************************************
;*<<<<<<<<<<<<<<<     EEPROM Page Write Function                 >>>>>>>>>>>>>>* 
;*******************************************************************************
;
        RSEG   ?PR?_WRITE_EE_PAGE?WRITE ;
; _
WRITE_EE_PAGE:
        CLR    EA
        MOV    DPH,R6  ; Address of EEPROM in R7/R6
        MOV    DPL,R7  ; 
;
        MOV    A,R3  ; Length of buffer in R3
        DEC    A     ; 
        ADD    A,R7             ; Calculate address of last
        MOV    ?_WRITE_EE_PAGE?END_ADDRESS+01H,A ; byte 
                            in page in XDATA.
        CLR    A                                 ;
        ADDC   A,R6                              ;
        MOV    ?_WRITE_EE_PAGE?END_ADDRESS,A     ;
;
        MOV    A,R5   ;  Address of buffer in IDATA in R5
        MOV    R0,A   ;
        ADD    A,R3     ;
        MOV    ?_WRITE_EE_PAGE?END_BUFFER,A ;
;   
LOOP:   MOV    A,@R0      ;
        MOVX   @DPTR,A    ;
        INC    R0         ;
        INC    DPTR       ;   
        MOV    A,R0       ;
        CJNE   A,?_WRITE_EE_PAGE?END_BUFFER,LOOP ;
;
        MOV    DPH,?_WRITE_EE_PAGE?END_ADDRESS      ;
        MOV    DPL,?_WRITE_EE_PAGE?END_ADDRESS+01H  ;
        DEC    R0         ;
;
CHECK:  XRL    P6,#08     ; Refresh watchdog on MAX691 
        MOVX   A,@DPTR    ; 
        CLR    C          ;
        SUBB   A,@R0      ;
        JNZ    CHECK      ;
;
        SETB   EA         ;
        RET               ; Return to C calling program
;
        END
;

14.2 Parameter Passing To Assembler Functions

In the assembler example the parameter current_ee_page was received in R6 and R7. Notice that the high byte is in the lower register, R6. The fact that the 8051 stores high bytes at the low address of any multiple byte object always causes head scratching!

The "_" prefix on the WRITE_EE_PAGE assembler function name is a convention to indicate that registers are used for parameter passing. If you are converting from C51 version <3.00, please bear this in mind.

Note that if you pass more parameters than the registers can cope with, additional space is taken in the default memory space (SMALL-data, COMPACT-pdata, LARGE-xdata).

14.3 Parameter Passing In Registers

Parameter passing is now possible via CPU registers (R0-R7). Coupled with register auto/local variables means that function calls can be made very quickly. Up to three parameters may be passed this way although when using long and/or float parameters only two may be passed, due to there being 4 bytes per variable and only 8 registers available! To maintain compatibility with 2.5x the NOREGPARMS #pragma is provided to force fixed memory locations to be used. Those calling assembler coded functions must take note of this.


Parameter Type    Char    Int+Spaced ptr   Long/Float       Generic Ptr
___________________________________________________________________________

Parameter   R7       R6/R7             R4-R7                R1,R2,R3
Parameter   R5       R4/R5             R4-R7                R1,R2,R3
Parameter   R3       R2/R3                                  R1,R2,R3


[Back] [Top] [Next]