265 lines
8.1 KiB
C
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);
|
|
}
|
|
}
|