Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original
cria_func.c
/* Luis Marcelo Fonseca - 0911762 - 3WB */
/* Marcello Lins - 0910675 - 3WB */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "definitions.h"
//Definicoes de Constantes
#define PUSH_EBP 0x55
#define MOVL 0x89
#define RET 0xc3
#define CALL 0xe8
// Vetores Estaticos
static unsigned char inicioDeFuncao[] = {PUSH_EBP,0x89,0xe5};
static unsigned char fimDeFuncao[] = {0x89,0xec,0x5d,RET};
static unsigned char callNaoConfigurado[] = {CALL,0xfc,0xff,0xff,0xff};
/*********************************************************
* Funcao Libera Malloc
*********************************************************/
void libera_func(void * func) {
free(func);
}
/*********************************************************
* Funcao Principal
*********************************************************/
void* cria_func (void* f, int n, Parametro params[]) {
// Variáveis
int indexaInstrucoes = 0;
int contador = 0;
int endFuncao;
int endProximaInstrucao;
int indiceProximaInstrucao;
int indiceDepoisDoCall;
int endCall;
unsigned char offset = 8;
unsigned char* pointer;
unsigned char * codigo = (unsigned char*) malloc(sizeof(unsigned char) * 255); // Tamanho maximo do vetor = 255
/************************
* Inicio do Código *
*************************/
// Adiciona instrucoes Iniciais no vetor de Instrucoes
for(contador = 0 ; contador < 3 ; contador ++ , indexaInstrucoes++)
{
codigo[contador] = inicioDeFuncao[contador];
}
// Para ler os parametros de tras para frente
for (contador = 0; contador < n ; contador++)
{
if (params[contador].e_constante == 0) {
if (params[contador].tipo == DOUBLE_PAR)
offset += 8;
else
offset += 4;
}
}
// Loop Principal, empilha os parametros de tras pra frente
for (contador = n - 1; contador >= 0; contador--)
{
// Se o parametro for Fixo
if (params[contador].e_constante)
{
codigo[indexaInstrucoes] = 0xb9; // mov $const, %ecx
if (params[contador].tipo == INT_PAR)
{
pointer = (unsigned char*) ¶ms[contador].valor.v_int;
codigo[indexaInstrucoes + 1] = *(pointer);
codigo[indexaInstrucoes + 2] = *(pointer + 1); /* Armazenando o int */
codigo[indexaInstrucoes + 3] = *(pointer + 2);
codigo[indexaInstrucoes + 4] = *(pointer + 3);
indexaInstrucoes += 5;
} /* Primeiro If Interno */
else
if (params[contador].tipo == CHAR_PAR)
{
pointer = (unsigned char*)¶ms[contador].valor.v_char;
codigo[indexaInstrucoes + 1] = *(pointer); // Armazenando o char
codigo[indexaInstrucoes + 2] = 0;
codigo[indexaInstrucoes + 3] = 0; // Zeramos os paddings
codigo[indexaInstrucoes + 4] = 0;
indexaInstrucoes += 5;
} /* Segundo If Interno*/
else
if (params[contador].tipo == PTR_PAR)
{
pointer = (unsigned char*)¶ms[contador].valor.v_ptr;
codigo[indexaInstrucoes + 1] = *(pointer);
codigo[indexaInstrucoes + 2] = *(pointer + 1); /* Armazenando o ponteiro */
codigo[indexaInstrucoes + 3] = *(pointer + 2);
codigo[indexaInstrucoes + 4] = *(pointer + 3);
indexaInstrucoes += 5;
} /* Terceiro If Interno*/
else
if (params[contador].tipo == DOUBLE_PAR)
{
pointer = (unsigned char*)¶ms[contador].valor.v_double;
codigo[indexaInstrucoes + 1] = *(pointer + 4);
codigo[indexaInstrucoes + 2] = *(pointer + 5); /* Armazenando o double */
codigo[indexaInstrucoes + 3] = *(pointer + 6);
codigo[indexaInstrucoes + 4] = *(pointer + 7); /* Salva em ordem de dois ints inversos */
codigo[indexaInstrucoes + 5] = 0x51; // Push %ecx
codigo[indexaInstrucoes + 6] = 0xb9; // Mov $const, %ecx
codigo[indexaInstrucoes + 7] = *(pointer + 0); /* mov $constant, %ecx */
codigo[indexaInstrucoes + 8] = *(pointer + 1);
codigo[indexaInstrucoes + 9] = *(pointer + 2); /* Precisa dar dois push */
codigo[indexaInstrucoes + 10] = *(pointer + 3);
indexaInstrucoes += 11;
} /* Quarto If Interno*/
else
printf("Erro - Tipo indefinido\n");
codigo [indexaInstrucoes] = 0x51; // Push %ecx
indexaInstrucoes++;
} /* If Externo */
else // Se Parametro Não For Fixo
{
if(params[contador].tipo == INT_PAR)
{
offset -= 4;
codigo[indexaInstrucoes + 0] = 0x8b; // mov offset(%ebp), %ecx
codigo[indexaInstrucoes + 1] = 0x4d;
codigo[indexaInstrucoes + 2] = offset;
indexaInstrucoes += 3;
} /* Primeiro If Interno*/
else
if(params[contador].tipo == CHAR_PAR)
{
offset -= 4;
codigo[indexaInstrucoes + 0] = 0x31; // xor %ecx, %ecx
codigo[indexaInstrucoes + 1] = 0xc9; // Precisa zerar o parametro, mas está errado
codigo[indexaInstrucoes + 2] = 0x8b; // mov offset(%ebp), %ecx
codigo[indexaInstrucoes + 3] = 0x4d;
codigo[indexaInstrucoes + 4] = offset;
indexaInstrucoes += 5;
} /* Segundo If Interno*/
else
if(params[contador].tipo == PTR_PAR)
{
offset -= 4;
codigo[indexaInstrucoes + 0] = 0x8b; // mov offset(%ebp), %ecx
codigo[indexaInstrucoes + 1] = 0x4d;
codigo[indexaInstrucoes + 2] = offset;
indexaInstrucoes += 3;
} /* Terceiro If Interno*/
else
if(params[contador].tipo == DOUBLE_PAR)
{
// Primeira parte do double
offset -= 4;
codigo[indexaInstrucoes + 0] = 0x8b; // mov offset(%ebp), %ecx
codigo[indexaInstrucoes + 1] = 0x4d;
codigo[indexaInstrucoes + 2] = offset; // Precisa ser ao contrario!
codigo[indexaInstrucoes + 3] = 0x51; // Push %ecx
offset -= 4; //
// Segunda parte do double
codigo[indexaInstrucoes + 4] = 0x8b; // mov offset(%ebp), %ecx
codigo[indexaInstrucoes + 5] = 0x4d;
codigo[indexaInstrucoes + 6] = offset; // Precisa ser ao contrario!
indexaInstrucoes += 7;
} /* Quarto If Inferno*/
codigo[indexaInstrucoes] = 0x51;
indexaInstrucoes++;
} /* Else Externo*/
} /* Loop Principal */
// Configurando o Endereço do Call
for(contador = 0 ; contador < 5 ; contador++,indexaInstrucoes++)
{
codigo[indexaInstrucoes] = callNaoConfigurado[contador];
}
// Desempilhando, Tirando o EBP da Pilha e RETORNO
for(contador = 0 ; contador < 4 ; contador++,indexaInstrucoes++)
{
codigo[indexaInstrucoes] = fimDeFuncao[contador];
}
//Procurando indice da próxima instrucao depois do CALL
contador=0;
while(codigo[contador]!= CALL)
{
contador++;
}
indiceProximaInstrucao = contador+5;
indiceDepoisDoCall = contador + 1;
//printf("\n****************************************");
//printf("\nIndice da Instrucao depois do Call : %d",indiceProximaInstrucao);
// Arrumando o Call
endFuncao = (int)f;
endProximaInstrucao = (int)&codigo[indiceProximaInstrucao];
endCall = endFuncao - endProximaInstrucao;
//printf("\nEndereco da Funcao : %x",endFuncao);
//printf("\nEndereco da Proxima Instrucao : %x",endProximaInstrucao);
//printf("\nEndereco do Call (offset) : %x",endCall);
//printf("\n****************************************\n");
*((int*) &codigo[indiceDepoisDoCall]) = endCall; // Casting do Endereco da proxima instrucao,para int* recebendo o endereco certo
// Testando o Vetor de Instrucoes
//traduzAssembly(codigo,indexaInstrucoes);
imprimeInstrucoes(codigo,indexaInstrucoes);
// Comentei as funções acima para que ficasse menos sobrecarregado
// e para facilitar a leitura da saida do programa
return codigo;
}
/*************************************************
* Faz o parsing do Conteúdo do Vetor de Codigo
* Traduzindo Código de máquina para a Assembly
* em Nossa Lingua Natal Tupiniquim :)
*************************************************/
void traduzAssembly(unsigned
char* codigo,int tamanho)
{
int contador = 0 ;
for( ; contador < tamanho ; contador ++)
{
switch(codigo[contador])
{
case PUSH_EBP:
printf("\nPUSH EBP");
break;
case MOVL:
if(codigo[contador+1] == 0xe5)
{
printf("\nMOVL ESP,EBP");
contador++;
}
else
if(codigo[contador+1] == 0xec)
{
printf("\nMOVL EBP,ESP");
contador++;
}
else
printf("\nMOVL ");
break;
case CALL:
contador++;
printf("\nCALL %x %x %x %x",codigo[contador],codigo[contador+1],codigo[contador+2],codigo[contador+3]);
contador = contador + 3;
break;
case RET:
printf("\nRET");
break;
case 0xb9:
printf("\nMOVL UMA CONSTANTE");
break;
case 0x51:
printf("\nPUSH ECX");
break;
default:
printf("\n Instrucao Sem Tratamento : %x",codigo[contador]);
break;
} /* switch*/
} /* for */
printf("\n\n==== Fim da Funcao de Traducao ====\n\n");
}
/*************************************************
* Imprime o código de máquina de cada instrucao
* com um índice antes(que é o indice no vetor de
* codigo). Ajuda a conferir a implementacao
*************************************************/
void imprimeInstrucoes(unsigned char* codigo,int tam)
{
int contador = 0 ;
printf("\n**********************************************\n");
while(contador<tam)
{
printf("\n%d - %x",contador,codigo[contador]);
contador++;
}
return ;
}
relatorio.txt
/* Luis Marcelo Fonseca - 0911762 - 3WB */
/* Marcello Lins - 0910675 - 3WB */
Para a realização dos testes foram utilizadas funções como as que seguem :
double myAdd(double b, int c, char d)
{
return b + (c * 2) + d;
}
// b = variavel, c = variavel, d = constante
// ---------------------------------------------------------- //
double myAdd(double b, double d)
{
return b + d;
}
// b = variavel, d = constante
// ---------------------------------------------------------- //
int myAdd(int a, int b)
{
return a * b;
}
// a = variavel, b = variavel
// ---------------------------------------------------------- //
int myAdd(char a, int b, char d)
{
return a * b * d;
}
// a = constante, b = variavel, d = constante
// ---------------------------------------------------------- //
int * myAdd(int * a, int b)
{
a = &b;
return a;
}
// a = variavel, b = constante
// ---------------------------------------------------------- //
double myAdd(double b, int c, char d, double o, double p, int u, char t, int x)
{
return b + c + d + o + p + u + t + x;
}
// b = variavel, c = variavel, d = variavel, t = variavel, resto constante.
// ---------------------------------------------------------- //
Observamos que os resultados foram satisfatorios, tendo em vista que todas elas funcionaram
e não observamos nenhum erro presente em outras funções testadas não listadas aqui.
Aprendemos as regras de empilhamento da pilha de execução, tendo sempre em mente que os parâmetros
devem ser empilhados de trás para frente para que a leitura seja possível.
Aprendemos também como funciona um call dinâmico, tendo que subtrair o endereço da função do endereço
da próxima instrução para obter o endereço do call.
Obs. Existem algumas funçoes que usamos para printar instruções na tela para ajudar com a criação
do programa. elas foram comentadas para que não fique muito complicado de ler.