Contenido>Indice>Intro CursoC51

EJEMPLO DE FUNCIÓN EN ENSAMBLADOR


No es difícil llamar a rutinas en ensamblador desde C51, si se lee este capítulo y el manual del usuario del compilador.

En contadas ocasiones el código generado por el compilador C51 no es adecuado para una determinada aplicación y se necesita recurrir al lenguaje ensamblador.

Si una función escrita en lenguaje ensamblador no recibe parámetros, la llamada a la misma es como la llamada a cualquier función C. Se necesita un prototipo de función extern antes de realizar una llamada a la misma:

Fichero C51:

extern void asm_func(void).

Fichero A51:

ASM_FUNC:  MOV  A,#10   ; instrucciones en ensamblador 8051

Si se deben pasar parámetros, C51 colocará los primeros parámetros en registros, tal como se apunta en esta sección.

La complicación aparece cuando todos los parámetros no caben en los registros. En este caso el usuario debe declarar un área de memoria en la que poder ubicar los parámetros extra. Así la función en ensamblador debe tener definido un segmento DATA conforme a los convenios sobre nombres esperados por C51.

En el ejemplo que sigue, el segmento

?DT?_WRITE_EE_PAGE?WRITE_EE SEGMENT DATA OVERLAYABLE

hace exactamente eso.

El mejor consejo es escribir un programa C que llame a la función en ensamblador, y compilarlo con la opción SRC para producir su equivalente en ensamblador. Luego debe observarse lo que hace C51 cuando llama la la función en ensamblador todavía sin escribir. Si se utiliza el nombre de segmento generado por C51 no habrá problemas.

Ejemplo de función en ensamblador con muchos parámetros

Llamada a función desde C

Las siguientes líneas deben añadirse al programa C que llama a la función en ensamblador:

#define UCHAR unsigned char
/* referencia "extern" a la rutina en ensamblador */
extern UCHAR write_ee_page(char*,UCHAR,UCHAR) ;

void dummy(void)
  {
  UCHAR number, eeprom_page_buffer, ee_page_length ; 
  char * current_ee_page ;
  
  number = write_ee_page (current_ee_page, 
       eeprom_page_buffer, ee_page_length) ;
  } /* FIN DE dummy */

 

La rutina en ensamblador es:

 

 NAME EEPROM_WRITE ;      
    
    PUBLIC  _WRITE_EE_PAGE              ; Esencial!!!
    PUBLIC  ?_WRITE_EE_PAGE?END_ADDRESS ;
    PUBLIC  ?_WRITE_EE_PAGE?END_BUFFER  ;
; 
P6     EQU  0FAH  ; 
Un pin del puerto P6 actúa sobre el watchdog
;*************************************************************** 
;*<<<<<<<<< Declarar los segmentos CODE y DATA para la
           Rutina en Ensamblador >>>>>>>>>>>* 
;**************************************************************; 
?PR?_WRITE_EE_PAGE?WRITE_EE SEGMENT CODE
?DT?_WRITE_EE_PAGE?WRITE_EE SEGMENT DATA OVERLAYABLE ; 
; 
;************************************************************** 
;*<<<<<< Declarar el área de memoria en RAM interna para 
       Variables locales, Etc. >>>>>>* 
;************************************************************** 
;
        RSEG ?DT?_WRITE_EE_PAGE?WRITE;
?_WRITE_EE_PAGE?END_ADDRESS:  DS   2   ;
?_WRITE_EE_PAGE?END_BUFFER:   DS   1   ;
;
;
;**************************************************************
;*<<<<<<<<<<<<<<<     Función de escritura de página EEPROM               
;**************************************************************
;
        RSEG   ?PR?_WRITE_EE_PAGE?WRITE ;
; _
WRITE_EE_PAGE:
        CLR    EA
        MOV    DPH,R6  ; Dirección de la EEPROM en R7/R6
        MOV    DPL,R7  ; 
;
        MOV    A,R3  ; Longitud del buffer en R3
        DEC    A     ; 
        ADD    A,R7  ; Calcular dirección del último byte de la
        MOV    ?_WRITE_EE_PAGE?END_ADDRESS+01H,A ; página en XDATA.
        CLR    A                                 ;
        ADDC   A,R6                              ;
        MOV    ?_WRITE_EE_PAGE?END_ADDRESS,A     ;
;
        MOV    A,R5   ; La dirección del buffer IDATA en 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     ; Refrescar el watchdog del MAX691 
        MOVX   A,@DPTR    ; 
        CLR    C          ;
        SUBB   A,@R0      ;
        JNZ    CHECK      ;
;
        SETB   EA         ;
        RET               ; Retorna al programa C
;
        END
;
 

   Contenido>Indice>Intro CursoC51