commit bff261fa01129da9135f95f16bf4124366ea24fe Author: pfaure Date: Mon Jun 21 14:04:17 2021 +0200 Version fonctionnelle processeur sécurisé diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bbf54f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +rondoudou_interpreter_registres +Tables/*.o +Lex_Yacc/as.output +Lex_Yacc/as.tab.* +Lex_Yacc/lex.yy.* +Lex_Yacc/as.dot diff --git a/Lex_Yacc/al.lex b/Lex_Yacc/al.lex new file mode 100644 index 0000000..6b69897 --- /dev/null +++ b/Lex_Yacc/al.lex @@ -0,0 +1,51 @@ +%{ +#include "as.tab.h" +int yywrap(void){return 1;} +void +yyerror (char const *s) +{ + + fprintf (stderr, "%s\n", s); +} + +%} + +%% + +"ADD" { return tADD ;} +"SUB" { return tSUB;} +"MUL" { return tMUL; } +"DIV" { return tDIV; } +"INF" { return tINF; } +"SUP" { return tSUP; } +"EQU" { return tEQU; } + +"AFC" { return tAFC; } +"CPY" { return tCPY; } + +"LOAD" { return tLOAD; } +"STORE" { return tSTORE; } +"LOADI" { return tLOADI; } +"STOREI" { return tSTOREI; } +"STOREA" { return tSTOREA; } + +"JMP" { return tJMP; } +"JMZ" { return tJMZ; } + +"GET" { return tGET; } +"PRI" { return tPRI; } + +"CALL" { return tCALL; } +"RET" { return tRET; } + +"STOP" { return tSTOP; } + +[0-9]+ { yylval.nombre = atoi(yytext); return tNB; } + +"\n" {} +" " {} +"\t" {} + +%% + + diff --git a/Lex_Yacc/as.y b/Lex_Yacc/as.y new file mode 100644 index 0000000..9a890d6 --- /dev/null +++ b/Lex_Yacc/as.y @@ -0,0 +1,83 @@ +%union { + int nombre; +} + +%{ +#include "../Tables/tables.h" +#include +%} + +%token tMUL tDIV tADD tSUB tINF tSUP tEQU +%token tAFC tCPY +%token tLOAD tSTORE tLOADI tSTOREI tSTOREA +%token tJMP tJMZ +%token tGET tPRI +%token tCALL tRET +%token tSTOP +%token tNB + +%% + +// Un programme est une suite d'au moins une instruction +Programme : Instruction Programme; +Programme : Instruction; + + +// Liste de toutes les instructions et conversion + +// MUL, ADD, DIV.... +Instruction : tMUL tNB tNB tNB {add_instruction(MUL, $2, $3, $4);}; +Instruction : tADD tNB tNB tNB {add_instruction(ADD, $2, $3, $4);}; +Instruction : tDIV tNB tNB tNB {add_instruction(DIV, $2, $3, $4);}; +Instruction : tSUB tNB tNB tNB {add_instruction(SUB, $2, $3, $4);}; +Instruction : tINF tNB tNB tNB {add_instruction(INF, $2, $3, $4);}; +Instruction : tSUP tNB tNB tNB {add_instruction(SUP, $2, $3, $4);}; +Instruction : tEQU tNB tNB tNB {add_instruction(EQU, $2, $3, $4);}; + +// AFC R val +Instruction : tAFC tNB tNB {add_instruction(AFC, $2, $3, 0);}; +// CPY R1 R2 +Instruction : tCPY tNB tNB {add_instruction(CPY, $2, $3, 0);}; + +// LOAD R @ +Instruction : tLOAD tNB tNB {add_instruction(LOAD, $2, $3, 0);}; +// STORE @ R +Instruction : tSTORE tNB tNB {add_instruction(STORE, $2, $3, 0);}; +// LOADI R R +Instruction : tLOADI tNB tNB {add_instruction(LOADI, $2, $3, 0);}; +// STOREI R R +Instruction : tSTOREI tNB tNB {add_instruction(STOREI, $2, $3, 0);}; +// STOREA @ R +Instruction : tSTOREA tNB tNB {add_instruction(STORE, $2, $3, 0);}; + +// JMP Ins +Instruction : tJMP tNB {add_instruction(JMP, $2, 0, 0);}; +// JMF @ Ins +Instruction : tJMZ tNB {add_instruction(JMZ, $2, 0, 0);}; + +// GET @ +Instruction : tGET tNB {add_instruction(GET, $2, 0, 0);}; +// PRI @ +Instruction : tPRI tNB {add_instruction(PRI, $2, 0, 0);}; + +// CALL Ins Val +Instruction : tCALL tNB tNB {add_instruction(CALL, $2, $3, 0);}; +// RET +Instruction : tRET {add_instruction(RET, 0, 0, 0);}; + +// STOP Val +Instruction : tSTOP tNB {add_instruction(STOP, $2, 0, 0);}; + +%% + +int main(int argc, char * argv[]) { + if (argc != 2) { + printf("Specifiez le fichier à interpreter"); + exit(2); + } + extern FILE * yyin; + yyin = fopen(argv[1], "r"); + yyparse(); + execute(); + return 0; +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..94003a8 --- /dev/null +++ b/Makefile @@ -0,0 +1,54 @@ +default : + @echo "Spécifiez une cible" + + + +########################### +### NETTOYAGE ### +########################### +clean_all : clean clean_Inputs clean_Outputs + +clean: clean_Lex_Yacc clean_Tables + @rm -f rondoudou_interpreter_registres + +clean_Tables: + @rm -f Tables/*.o + +clean_Lex_Yacc: + @rm -f Lex_Yacc/as.output Lex_Yacc/as.tab.* Lex_Yacc/lex.yy.* Lex_Yacc/as.dot + +clean_Inputs: + @rm -f Inputs/* + +clean_Outputs: + @rm -f Outputs/* + + + +########################### +### COMPILATION ### +########################### +build : clean build_Tables build_Lex_Yacc + gcc Lex_Yacc/as.tab.o Lex_Yacc/lex.yy.o Tables/tables.o -ll -o rondoudou_interpreter_registres + +build_Tables: clean_Tables + gcc -c Tables/tables.c -o Tables/tables.o + +build_Lex_Yacc: clean_Lex_Yacc + bison -g -v -d -t -b Lex_Yacc/as Lex_Yacc/as.y + flex -o Lex_Yacc/lex.yy.c Lex_Yacc/al.lex + gcc -c Lex_Yacc/as.tab.c -o Lex_Yacc/as.tab.o + gcc -c Lex_Yacc/lex.yy.c -o Lex_Yacc/lex.yy.o + + + +########################### +### EDITION ### +########################### +edit_Lex_Yacc: + pluma Lex_Yacc/al.lex Lex_Yacc/as.y & + +edit_Tables: + pluma Tables/tables.c Tables/tables.h & + +edit: edit_Lex_Yacc edit_Tables diff --git a/ReadMe.md b/ReadMe.md new file mode 100644 index 0000000..0e62437 --- /dev/null +++ b/ReadMe.md @@ -0,0 +1,45 @@ +# Processeur sécurisé - Interpreteur + + + +Afin de pouvoir tester le code que nous avons compilé depuis le C avec notre compilateur, nous avons crée un interpreteur pour simuler l'execution du code assembleur + +# Utilisation du cross assembleur + +Un Makefile a été inclus au sous module Interpreteur afin de simplifier son utilisation. Ainsi, afin de compiler tout l'Interpreteur, il suffit de de rentrer la commande. +``` bash +make build +``` +Pour lancer l'Interpretation du code qui aura été préalablement généré avec notre compilateur, il suffit de lancer la commande +``` bash +cat FicherASM | ./rondoudou_interpreter +``` +Les prints et gets du programme auront lieu dans le terminal. + + + +NB : Il est possible de rester au niveau du projet général. Un Makefile est aussi présent. Pour compiler l'Interpreteur uniquement : +``` bash +make compile QUOI="interpreteur" +``` +Pour compiler le projet en entier : +``` bash +make compile QUOI="all" +``` + +Pour interpreter le fichier ***file_name.memasm*** : +``` bash +make exec SOURCE="file_name" QUOI="interprete" +``` +Pour compiler, cross assembler et interpreter le fichier ***file_name.c*** et générer les fichiers ***file_name.memasm***, ***file_name.regasm***, ***file_name.bin***, et, copier le code binaire dans le fichier ***../Processeur/Processeur.srcs/sources1/new/MemoireInstructions.vhd*** : +``` bash +make exec SOURCE="file_name" QUOI="all" +``` + +# Implémentation + +L'implémentation a été réalisée grâce à Lex/Yacc. Le parseur charge le programme dans un buffer, puis une méthode d'execution est lancée. + + + + diff --git a/Tables/tables.c b/Tables/tables.c new file mode 100644 index 0000000..0d040ae --- /dev/null +++ b/Tables/tables.c @@ -0,0 +1,248 @@ +#include "tables.h" +#include +#include + +#define TAILLE_BUFFER_INSTRUCTIONS (1024) +#define TAILLE_MEMOIRE (32) +#define TAILLE_PILE_APPELS (16) +#define TAILLE_BANC_REGISTRES (16) + + +/**************************************************/ +/**************************************************/ +/************ 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); + 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 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) { + printf("Veuillez saisir un nombre : \n"); + scanf("%d", &(registres[check_registre(programme[eip].param1)])); + } else if (programme[eip].instruction == PRI) { + printf("%d@%d\n", registres[check_registre(programme[eip].param1)], programme[eip].param1); + + } else if (programme[eip].instruction == CALL) { + 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 if (programme[eip].instruction == RET) { + esp--; + eip = pile[check_adresse_pile(esp)] - 1; + esp--; + ebp = pile[check_adresse_pile(esp)]; + + } else if (programme[eip].instruction == STOP) { + if (programme[eip].param1 == 0) { + continuer = 0; + print(); + print_reg(); + } + } + eip = (eip + 1) % TAILLE_BUFFER_INSTRUCTIONS; + //printf("EIP : %d ; Z : %d\n", eip, Z); + } +} diff --git a/Tables/tables.h b/Tables/tables.h new file mode 100644 index 0000000..1a1d928 --- /dev/null +++ b/Tables/tables.h @@ -0,0 +1,14 @@ +#ifndef TABLE_H +#define TABLE_H + + +// Enum of the instruction +enum instruction_t {ADD, MUL, SUB, DIV, INF, SUP, EQU, CPY, AFC, LOAD, STORE, LOADI, STOREI, STOREA, JMP, JMZ, PRI, GET, CALL, RET, STOP}; + +// Add a new instruction +void add_instruction(enum instruction_t inst, int param1, int param2, int param3); + +// Execute the program +void execute(); + +#endif