Interpreteur (sans mémoire sécurisée)

This commit is contained in:
Paul Faure 2021-06-18 09:21:24 +02:00
commit 9c38352e61
7 changed files with 436 additions and 0 deletions

6
.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
rondoudou_interpreter
Tables/*.o
Lex_Yacc/as.output
Lex_Yacc/as.tab.*
Lex_Yacc/lex.yy.*
Lex_Yacc/as.dot

50
Lex_Yacc/al.lex Normal file
View file

@ -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" {}
%%

72
Lex_Yacc/as.y Normal file
View file

@ -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<nombre> 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;
}

54
Makefile Normal file
View file

@ -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

45
ReadMe.md Normal file
View file

@ -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.

195
Tables/tables.c Normal file
View file

@ -0,0 +1,195 @@
#include "tables.h"
#include <stdio.h>
#include <stdlib.h>
#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<TAILLE_MEMOIRE; i++) {
printf("mem[%d] = %d\n", i, mem[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) {
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 == SUB) {
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 == MUL) {
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 == DIV) {
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 == INF) {
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 == SUP) {
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 == 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);
}
}

14
Tables/tables.h Normal file
View file

@ -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