#include <stdio.h>
#include <stdlib.h>
#include "cria_func.h"



void* cria_func (void* f, int n, Parametro params[]){
	unsigned char* a;
	int i=n-1;
	unsigned int j=0;
	unsigned int k=15;
  	unsigned int z=0;
  	unsigned int conta_int_ou_ptr_nao_constante=0;
	unsigned int conta_char_nao_constante=0;
	unsigned int conta_double_nao_constante=0; 
  	unsigned int acumula_nao_constante=0;
  	unsigned char ac=0;
  	unsigned char* b;
  	unsigned char p=0;
	while(j<n){
		if(params[j].e_constante){
			if(params[j].tipo == INT_PAR)
				k=k+5+1;
			else if(params[j].tipo == CHAR_PAR)
				k=k+2;
			else if(params[j].tipo == DOUBLE_PAR)
				k=k+12;
			else k=k+5+1;
			}
		else
         if(params[j].tipo == CHAR_PAR){
				conta_char_nao_constante++;
            k=k+5;
         }
			else if(params[j].tipo == DOUBLE_PAR){
				conta_double_nao_constante++;
            k=k+6;
         }
			else {
            conta_int_ou_ptr_nao_constante++;
            k=k+3;
         }
   j++;
   }
   
   acumula_nao_constante = 4*conta_int_ou_ptr_nao_constante + 
   4*conta_char_nao_constante + 8*conta_double_nao_constante;
   ac=8+acumula_nao_constante;
   
   
   a= malloc(k * sizeof(unsigned char));
   
	a[z] = 0x55;  z++;                        /*push   %ebp*/
   a[z] = 0x89;  z++; a[z] = 0xe5;  z++;    /* mov    %esp,%ebp*/
   


	while(i>=0){
      
      if(params[i].e_constante){
         
         if(params[i].tipo == INT_PAR){
            b= (unsigned char*)&(params[i].valor.v_int);
            j=0;
            a[z]=0xb8; z++;
            while(j<4){
            a[z]= b[j];
            z++;
            j++;
            }/*mov $0x00 0x00 0x00 0x00, %eax*/
            a[z]=0x50; z++; /*pushl %eax*/
            p++;
         }
         else if(params[i].tipo == CHAR_PAR){
          





            a[z]=0x6a; z++;
            a[z]=(params[i].valor.v_char); z++; /*push 0x00*/
            p++;
         }
         else if(params[i].tipo == DOUBLE_PAR){
            b= (unsigned char*)&(params[i].valor.v_double);
            j=0;
            a[z]=0xb8;  z++;
            while(j<4){
            a[z]= b[j]; 
            z++;
            j++;
            }/*mov 0x00000000, %eax*/
            a[z]=0xba;  z++;
            while(j<8){
            a[z]= b[j]; 
            z++;
            j++;
            }/*mov 0x00000000, %edx*/
            a[z]=0x52;  z++; /*push %edx*/
            p++;
            a[z]=0x50;  z++; /*push %eax*/
            p++;
         }
         else{
            
         b= (unsigned char*)&(params[i].valor.v_ptr);
            j=0;
            a[z]=0xb8; z++;
            while(j<4){
            a[z]= b[j];
            z++;
            j++;
            }/*mov $0x00 0x00 0x00 0x00, %eax*/
            a[z]=0x50; z++; /*pushl %eax*/
            p++;
         }
      }
      
      
      
      else{
         if(params[i].tipo == INT_PAR){
         ac=ac-4;
         a[z]=0xff; z++; a[z]=0x75; z++; a[z]=ac; z++;/*pushl  0x00(%ebp)*/ 
         p++;   
         }
         else if(params[i].tipo == CHAR_PAR){
         ac=ac-4;   
         a[z]=0x0f; z++; a[z]=0xbe; z++; a[z]=0x45; z++; a[z]=ac; z++; 
            /* movsbl 0x00(%ebp),%eax*/ 
         a[z]=0x50; z++;   /* push   %eax*/
         p++;
         }
         else if(params[i].tipo == DOUBLE_PAR){
         ac=ac-4;   
         a[z]=0xff;  z++; a[z]=0x75; z++; a[z]=ac; z++;/*pushl  0x00(%ebp)*/ 
         p++;
         ac=ac-4;
         a[z]=0xff; z++; a[z]=0x75;  z++; a[z]=ac; z++;/*pushl  0x00(%ebp)*/
         p++;
         }
         else{
         ac=ac-4;   
         a[z]=0xff; z++; a[z]=0x75; z++; a[z]=ac;  z++;/*pushl  0x00(%ebp)*/ 
         p++;
         }
      }
	  i--;
   }
   a[z]=0xb8;   z++; /*mov $0x00 0x00 0x00 0x00 %eax*/
   b= (unsigned char*)&f;
   j=0;
   while(j<4){
   a[z]= b[j]; 
   z++;
   j++;
   }
   a[z]=0xff; z++; a[z]=0xd0; z++; /*call %eax*/
				
   p=p*4;
   a[z]=0x83; z++; a[z]=0xc4; z++; a[z]=p; z++; /*add $0xp, %esp*/
   a[z]=0xc9;  z++; /*leave*/
   a[z]=0xc3;  z++; /*ret*/
   
   j=0;   
   
   return a;
}

void libera_func (void* func){
   free (func);
}