From 9c38352e612609ceb06ea82c10c31790e89feae8 Mon Sep 17 00:00:00 2001 From: pfaure Date: Fri, 18 Jun 2021 09:21:24 +0200 Subject: [PATCH] =?UTF-8?q?Interpreteur=20(sans=20m=C3=A9moire=20s=C3=A9cu?= =?UTF-8?q?ris=C3=A9e)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 ++ Lex_Yacc/al.lex | 50 +++++++++++++ Lex_Yacc/as.y | 72 ++++++++++++++++++ Makefile | 54 ++++++++++++++ ReadMe.md | 45 +++++++++++ Tables/tables.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++ Tables/tables.h | 14 ++++ 7 files changed, 436 insertions(+) create mode 100644 .gitignore create mode 100644 Lex_Yacc/al.lex create mode 100644 Lex_Yacc/as.y create mode 100644 Makefile create mode 100644 ReadMe.md create mode 100644 Tables/tables.c create mode 100644 Tables/tables.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6fcd227 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +rondoudou_interpreter +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..b935478 --- /dev/null +++ b/Lex_Yacc/al.lex @@ -0,0 +1,50 @@ +%{ +#include "as.tab.h" +int yywrap(void){return 1;} +void +yyerror (char const *s) +{ + + fprintf (stderr, "%s\n", s); +} + +%} + +%% + +"ADD" { return tADD ;} +"SOU" { return tSUB;} +"MUL" { return tMUL; } +"DIV" { return tDIV; } +"INF" { return tINF; } +"SUP" { return tSUP; } +"EQU" { return tEQU; } + +"AFC" { return tAFC; } +"COP" { return tCPY; } +"AFCA" { return tAFCA; } + + +"READ" { return tREAD; } +"WR" { return tWR; } + +"JMP" { return tJMP; } +"JMF" { return tJMF; } + +"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..6f9f51c --- /dev/null +++ b/Lex_Yacc/as.y @@ -0,0 +1,72 @@ +%union { + int nombre; +} + +%{ +#include "../Tables/tables.h" +%} + +%token tMUL tDIV tADD tSUB tINF tSUP tEQU +%token tAFC tCPY tAFCA +%token tREAD tWR +%token tJMP tJMF +%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 @ val +Instruction : tAFC tNB tNB {add_instruction(AFC, $2, $3, 0);}; +// CPY @ @ +Instruction : tCPY tNB tNB {add_instruction(CPY, $2, $3, 0);}; +// AFCA @ val +Instruction : tAFCA tNB tNB {add_instruction(AFCA, $2, $3, 0);}; + +// JMP Ins +Instruction : tJMP tNB {add_instruction(JMP, $2, 0, 0);}; +// JMF @ Ins +Instruction : tJMF tNB tNB {add_instruction(JMF, $2, $3, 0);}; + +// READ @1 @2 +Instruction : tREAD tNB tNB {add_instruction(READ, $2, $3, 0);}; +// WR @1 @2 +Instruction : tWR tNB tNB {add_instruction(WRITE, $2, $3, 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(void) { + yyparse(); + execute(); + return 0; +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7e8a2b0 --- /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 + +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 + +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..a5cf97d --- /dev/null +++ b/Tables/tables.c @@ -0,0 +1,195 @@ +#include "tables.h" +#include +#include + +#define TAILLE_BUFFER_INSTRUCTIONS (1024) +#define TAILLE_MEMOIRE (64) + + +/**************************************************/ +/**************************************************/ +/************ 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; + +// Memoire du programme +int mem[TAILLE_MEMOIRE]; + +// Pointeur de base dans la mémoire +int ebp = 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\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 mem[check_adresse(ebp + programme[eip].param3)]; + } else if (programme[eip].instruction == EQU) { + mem[check_adresse(ebp + programme[eip].param1)] = mem[check_adresse(ebp + programme[eip].param2)] == mem[check_adresse(ebp + programme[eip].param3)]; + + + } else if (programme[eip].instruction == AFC) { + mem[check_adresse(ebp + programme[eip].param1)] = programme[eip].param2; + } else if (programme[eip].instruction == CPY) { + mem[check_adresse(ebp + programme[eip].param1)] = mem[check_adresse(ebp + programme[eip].param2)]; + } else if (programme[eip].instruction == AFCA) { + mem[check_adresse(ebp + programme[eip].param1)] = ebp + programme[eip].param2; + + } else if (programme[eip].instruction == READ) { + mem[check_adresse(ebp + programme[eip].param1)] = mem[check_adresse(mem[check_adresse(ebp + programme[eip].param2)])]; + } else if (programme[eip].instruction == WRITE) { + mem[check_adresse(mem[check_adresse(ebp + programme[eip].param1)])] = mem[check_adresse(ebp + programme[eip].param2)]; + + } else if (programme[eip].instruction == JMP) { + eip = programme[eip].param1 - 1; + } else if (programme[eip].instruction == JMF) { + if (!mem[check_adresse(ebp + programme[eip].param1)]) { + eip = programme[eip].param2 - 1; + } + + } else if (programme[eip].instruction == GET) { + printf("Veuillez saisir un nombre : \n"); + scanf("%d", &(mem[check_adresse(ebp + programme[eip].param1)])); + } else if (programme[eip].instruction == PRI) { + printf("%d@%d\n", mem[check_adresse(ebp + programme[eip].param1)], ebp + programme[eip].param1); + + } else if (programme[eip].instruction == CALL) { + 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) { + eip = mem[check_adresse(ebp - 1)] - 1; + ebp = mem[check_adresse(ebp - 2)]; + + } else if (programme[eip].instruction == STOP) { + if (programme[eip].param1 == 0) { + continuer = 0; + } + } + eip = (eip + 1) % TAILLE_BUFFER_INSTRUCTIONS; + //printf("EIP : %d \n", eip); + } +} diff --git a/Tables/tables.h b/Tables/tables.h new file mode 100644 index 0000000..e193a33 --- /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, AFCA, READ, WRITE, JMP, JMF, 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