InterpreteurRegistres/Tables/tables.c
Faure Paul 510d9c2d6c Clean
2022-06-27 21:46:01 +02:00

265 lines
8.1 KiB
C

#include "tables.h"
#include <stdio.h>
#include <stdlib.h>
#define TAILLE_BUFFER_INSTRUCTIONS (1024)
#define TAILLE_MEMOIRE (64)
#define TAILLE_PILE_APPELS (4)
#define TAILLE_BANC_REGISTRES (16)
#define SECURED (1)
/**************************************************/
/**************************************************/
/************ Variables et structures *************/
/**************************************************/
/**************************************************/
// Structure coding an instruction
struct str_instruction {
enum instruction_t instruction;
int param1;
int param2;
int param3;
};
// Buffer stockant le programme
struct str_instruction programme[TAILLE_BUFFER_INSTRUCTIONS * sizeof(struct str_instruction)];
// Pointeur d'instruction
int eip = 0;
// Banc de registre
int registres[TAILLE_BANC_REGISTRES];
// Memoire du programme
int mem[TAILLE_MEMOIRE];
// Pointeur de base dans la mémoire
int ebp = 0;
// Memoire du programme
int pile[TAILLE_PILE_APPELS];
// Pointeur de sommet dans la pile d'appel
int esp = 0;
// Flag Z
int Z = 0;
/**************************************************/
/**************************************************/
/******* Fonctions internes de verification *******/
/**************************************************/
/**************************************************/
// Verifie qu'une adresse est bien en mémoire (renvoi l'adresse si oui, leve une exception si non)
int check_adresse(int adresse) {
if (adresse >= TAILLE_MEMOIRE || adresse < 0) {
printf("\033[31;01m ERROR : \033[00m Segmentation fault de %d avec eip = %d et ebp = %d\n", adresse, eip, ebp);
print();
print_reg();
exit(2);
}
return adresse;
}
// Verifie qu'un numéro de registre est valide
int check_registre(int registre) {
if (registre >= TAILLE_BANC_REGISTRES || registre < 0) {
printf("\033[31;01m ERROR : \033[00m Register error\n");
exit(2);
}
return registre;
}
// Verifie que les limites de la mémoire d'appels ne sont pas franchies
int check_adresse_pile(int adresse) {
if (adresse >= TAILLE_PILE_APPELS || adresse < 0) {
printf("\033[31;01m ERROR : \033[00m Stack error\n");
exit(2);
}
return adresse;
}
// Verifie que eip ne depasse pas la taille du buffer
int check_eip(int eip) {
if (eip >= TAILLE_BUFFER_INSTRUCTIONS) {
printf("\033[31;01m ERROR : \033[00m Taille du buffer insuffisante pour charger le programme\n");
exit(2);
} else if (eip < 0) {
printf("\033[31;01m ERROR : \033[00m EIP < 0\n");
exit(2);
}
return eip;
}
/**************************************************/
/**************************************************/
/********** Fonction interne d'affichage **********/
/**************************************************/
/**************************************************/
// Affiche la mémoire
void print() {
int i;
printf("EBP : %d\n", ebp);
for (i=0; i<TAILLE_MEMOIRE; i++) {
printf("mem[%d] = %d\n", i, mem[i]);
}
}
// Affiche les registres
void print_reg() {
int i;
for (i=0; i<TAILLE_BANC_REGISTRES; i++) {
printf("registres[%d] = %d\n", i, registres[i]);
}
}
/**************************************************/
/**************************************************/
/************** Instructions Writing **************/
/**************************************************/
/**************************************************/
// Add a new instruction
void add_instruction(enum instruction_t inst, int param1, int param2, int param3) {
struct str_instruction my_instruction = {inst, param1, param2, param3};
programme[check_eip(eip)] = my_instruction;
eip++;
}
/**************************************************/
/**************************************************/
/************* Execution du programme *************/
/**************************************************/
/**************************************************/
// execute le programme
void execute() {
printf("Debut de l'interpretation\n");
eip = 0;
int continuer = 1;
while (continuer) {
if (programme[eip].instruction == ADD) {
registres[check_registre(programme[eip].param1)] = registres[check_registre(programme[eip].param2)] + registres[check_registre(programme[eip].param3)];
} else if (programme[eip].instruction == SUB) {
registres[check_registre(programme[eip].param1)] = registres[check_registre(programme[eip].param2)] - registres[check_registre(programme[eip].param3)];
Z = !registres[check_registre(programme[eip].param1)];
} else if (programme[eip].instruction == MUL) {
registres[check_registre(programme[eip].param1)] = registres[check_registre(programme[eip].param2)] * registres[check_registre(programme[eip].param3)];
} else if (programme[eip].instruction == DIV) {
registres[check_registre(programme[eip].param1)] = registres[check_registre(programme[eip].param2)] / registres[check_registre(programme[eip].param3)];
} else if (programme[eip].instruction == INF) {
registres[check_registre(programme[eip].param1)] = registres[check_registre(programme[eip].param2)] < registres[check_registre(programme[eip].param3)];
} else if (programme[eip].instruction == SUP) {
registres[check_registre(programme[eip].param1)] = registres[check_registre(programme[eip].param2)] > registres[check_registre(programme[eip].param3)];
} else if (programme[eip].instruction == EQU) {
registres[check_registre(programme[eip].param1)] = registres[check_registre(programme[eip].param2)] == registres[check_registre(programme[eip].param3)];
} else if (programme[eip].instruction == AFC) {
registres[check_registre(programme[eip].param1)] = programme[eip].param2;
} else if (programme[eip].instruction == CPY) {
registres[check_registre(programme[eip].param1)] = registres[check_registre(programme[eip].param2)];
} else if (programme[eip].instruction == LOAD) {
registres[check_registre(programme[eip].param1)] = mem[check_adresse(ebp + programme[eip].param2)];
} else if (programme[eip].instruction == STORE) {
mem[check_adresse(ebp + programme[eip].param1)] = registres[check_registre(programme[eip].param2)];
} else if (programme[eip].instruction == LOADI) {
registres[check_registre(programme[eip].param1)] = mem[check_adresse(registres[check_registre(programme[eip].param2)])];
} else if (programme[eip].instruction == STOREI) {
mem[check_adresse(registres[check_registre(programme[eip].param1)])] = registres[check_registre(programme[eip].param2)];
} else if (programme[eip].instruction == STOREA) {
mem[check_adresse(ebp + programme[eip].param1)] = registres[check_registre(programme[eip].param2)] + ebp;
} else if (programme[eip].instruction == JMP) {
eip = programme[eip].param1 - 1;
} else if (programme[eip].instruction == JMZ) {
if (Z) {
eip = programme[eip].param1 - 1;
}
} else if (programme[eip].instruction == GET) {
scanf("%d", &(registres[check_registre(programme[eip].param1)]));
} else if (programme[eip].instruction == PRI) {
printf("%d", registres[check_registre(programme[eip].param1)]);
} else if (programme[eip].instruction == PRIC) {
printf("%c", registres[check_registre(programme[eip].param1)]);
} else if (programme[eip].instruction == CALL) {
if (SECURED) {
pile[check_adresse_pile(esp)] = ebp;
esp++;
pile[check_adresse_pile(esp)] = eip + 1;
esp++;
ebp = ebp + programme[eip].param2;
eip = programme[eip].param1 - 1;
} else {
mem[check_adresse(ebp + programme[eip].param2)] = ebp;
mem[check_adresse(ebp + programme[eip].param2 + 1)] = eip + 1;
ebp = ebp + programme[eip].param2 + 2;
eip = programme[eip].param1 - 1;
}
} else if (programme[eip].instruction == RET) {
if (SECURED) {
esp--;
eip = pile[check_adresse_pile(esp)] - 1;
esp--;
ebp = pile[check_adresse_pile(esp)];
} else {
int lastebp = ebp;
eip = mem[check_adresse(ebp - 1)] - 1;
ebp = mem[check_adresse(ebp - 2)];
mem[check_adresse(lastebp - 2)] = mem[check_adresse(lastebp)];
}
} else if (programme[eip].instruction == STOP) {
if (programme[eip].param1 == 0) {
continuer = 0;
}
}
eip = (eip + 1) % TAILLE_BUFFER_INSTRUCTIONS;
//printf("EIP : %d ; Z : %d\n", eip, Z);
}
}