Contenido>Indice>Intro CursoC51

FUNCIONES In-line EN C51


Uno de los fundamentos de C es que las funciones tienen bien definido el mecanismo de entrada y salida. Esto significa que los parámetros de entrada se colocan en un área definida, en la pila o en los registros, y luego se ejecuta un CALL. Inevitablemente, la instrucción de llamada guarda dos bytes en la pila (la dirección de retorno).

En la mayoría de las aplicaciones del 8051, esto no es ningún problema, ya que generalmente se dispone de 256 bytes de RAM interna para la pila, lo que permite funciones con un elevado nivel de anidamiento.

Sin embargo en el caso del 8031 y de un reducido número de dispositivos tales como el 87C751, cada byte de RAM interna es crítico. En el último caso solo se dispone de 64 bytes.

Un truco que permite salvar espacio en la pila y reducir el tiempo de ejecución es utilizar macros con parámetros que actúan como funciones "in-line". Aunque el uso de macros con parámetros no es una práctica habitual, puede resultar muy útil en variantes del 8051 con limitada RAM interna.

En el siguiente ejemplo, el trabajo de la función strcpy() lo realiza una macro llamada "Inline_Strcpy", que aunque parece una función normal, no posee una dirección fija ni un área para datos propia. El carácter '\' sirve para que la definición de la macro pueda continuar en varias líneas.

Estas funciones se llaman como las funciones normales, con los parámetros metidos dentro de ( ). Sin embargo no se utiliza un CALL porque el código necesario se crea en el punto de llamada "in-line". El resultado final es que se realiza el trabajo de strcpy pero sin necesidad de usar la pila.

La desventaja de este método, en este ejemplo concreto, es que los apuntadores a la fuente y al destino se modifican durante el proceso de copia.

Un beneficio adicional en este ejemplo es que los punteros s1 y s2, son punteros específicos, y por lo tanto muy eficientes. Los lentos punteros genéricos no son necesarios aunque haya que copiar datos en distintas áreas de memoria.

#define Inline_Strcpy(s1,s2)  { while((*s1 = *s2) != 0))\ 
                                 {*s1++ ; *s2++; }\
                              }
char xdata *out_buffx = "                           " ;
char xdata *in_buffx  = "Hello" ; 
char idata *in_buffi  = "Hello" ;
char idata *out_buffi = "                           " ;  
char code *in_buffc   = "Hello" ;

void main(void) {

   Inline_Strcpy(out_buffx,in_buffx)  /* funciones In-line */
   Inline_Strcpy(out_buffi,in_buffi)
   Inline_Strcpy(out_buffx,in_buffc)
   }

 

El cálculo de la interpolación realizado originalmente por una subrutina, puede redefinirse fácilmente como una macro de 5 parámetros, minimizando el uso de RAM y el tiempo de ejecución a costa del tamaño del código. Notar que 'r', el quinto parámetro, representa el valor de retorno que hay que pasar a la macro, para que pueda poner el resultado en algún sitio.

#define UCHAR unsigned char
#define UINT  unsigned int

#define interp_sub(x,y,n,d,r)  y -= x ; \ 
if(!CY) { r = (UCHAR) (x + (UCHAR)(((UINT)(n *  y))/d)) ; }\ 
else    { r = (UCHAR) (x - (UCHAR)(((UINT)(n * -y))/d)) ; }  

Esta macro se llama en:

/*Interpolar valores 2D */
/*Uso de macro con parámetros*/

interp_sub(map_x1y1,map_x2y1,x_temp1,x_temp2,result_y1) 

más tarde se reutiliza con otros parámetros así:

interp_sub(map_x1y2,map_x2y2,x_temp1,x_temp2,result_y2) 

 

Para resumir, las macros con parámetros proporcionan un buen mecanismo para ordenar a C51 la ejecución de operaciones con distintos valores de entrada, en programas en los que la velocidad o el espacio en RAM es crítico. 


   Contenido>Indice>Intro CursoC51