Máquina virtual

Publicado por Gabriel (última atualização em 25/05/2010)

[ Hits: 7.353 ]

Download virtual.c




Exemplo bem simples de uma máquina virtual em C. Consiste em ler um conjunto de códigos e interpretá-los. Por exemplo, as seguintes instruções:

51 0 30 0 1 27 1 41 10 12 1 2 2 53 1 40 -10 50 2 -1 1000 0 0 1 0 2 1 -1

Calculam o fatorial de um número, independente do SO em que o programa abaixo (máquina virtual) está compilado. Qualquer dúvida comentem que em breve irei responder.

  



Esconder código-fonte

/*******************************************************************/
/**                                                  **/
/**   Arquivo: virtual.c                                          **/
/**   Editor Utilizado: gedit 2.26.1                              **/
/**   Compilador: gcc version 4.3.3                               **/
/**                                                               **/
/**   Descrição: processador virtual simples                      **/ 
/**                                                               **/
/**   Observacoes: 1. _P_EXEMPLO e um trecho de codigo utilizado  **/
/**                   para a depuracao de erros sendo possivel    **/
/**                   modifica-lo. Por padrao, deixei desativado; **/
/**                2. Optei por utilizar um vetor de inteiros     **/
/**                   para armazenar as instrucoes para resolver  **/
/**                   alguns problemas;                           **/
/**                3. Nao utilizei mais de 1024 instrucoes para   **/
/**                   verificar possiveis problemas;              **/
/**                4. Assim como a linguagem C, resolvi nao       **/
/**                   tratar os erros referentes aos              **/
/**                   registradores. Ou seja, e possivel utilizar **/
/**                   um valor de reg[300], por exemplo, vai      **/
/**                   do bom senso do usuario-programador ...     **/
/**                                                               **/
/**   Data da Ultima Modificacao: 14/mai/2010                     **/
/**                                                  **/
/*******************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAXMEM 1024      /* tamanho maximo do programa */
#define MAXREG 256      /* quantidade maxima de registradores */

#undef _P_EXEMPLO      /* programa exemplo utilizado para testes */

double reg[MAXREG];      /* registradores */
int prog[MAXMEM];      /* instrucoes */

int pi = 0;            /* ponteiro de instrucao */
int e = 0;            /* registrador de estado */

char line[100];         /* linha de comando */
char concluido = 0;      /* variavel de passagem para while */
int n_int = 0;         /* armazena o numero de intrucoes do programa */

int t_reg = 0;          /* registrador temporario */
double t_i = 0;         /* valor do registrador temporario */

int main (){

   #ifdef _P_EXEMPLO
   
   /* Fatorial */
   
   prog[0] = 51; 
   prog[1] = 0;
   prog[2] = 30;
   prog[3] = 0;
   prog[4] = 1;
   prog[5] = 27;
   prog[6] = 1;
   prog[7] = 41;
   prog[8] = 10;
   prog[9] = 12;
   prog[10] = 1;
   prog[11] = 2;
   prog[12] = 2;
   prog[13] = 53;
   prog[14] = 1;
   prog[15] = 40;
   prog[16] = -10;
   prog[17] = 50;
   prog[18] = 2;
   prog[19] = -1;
   prog[20] = 1000;
   
   /* Inicializacoes */
   
   reg[0] = 0;
   reg[1] = 0;
   reg[2] = 1;
   
   n_int = 20;
   
   #else
   
   /*************    LEITURA DAS INSTRUCOES   **************/
      
   pi = -1;
   n_int = 0;
   printf("\nInforme as instrucoes: \n\n");

    do {
   
      /* le a instrucao */

       ++pi;
       scanf("%d", &prog[pi]);
      
   } while (prog[pi] != 1000);

   n_int = pi;   
   
   /* inicializacoes */

   concluido = 0;
   while (!concluido) {
      
      scanf("%d", &t_reg);
      
      if (t_reg == -1) {   /* para sair */
      
         concluido = 1;
      
      } else {   

          scanf("%lf", &t_i);    
         reg[t_reg] = t_i;
         t_reg = 0;
         t_i = 0;
               
      }
      
   }

   #endif

   
   /*************    EXECUCAO    *************/

   printf("\nExecutando...\n\n");
   concluido = 0;
   pi = 0;

   while ((pi <= n_int)&&(!concluido)) {
   
      switch (prog[pi]) { 
         
         /****** ARITMETICOS ******/
      
         case 10: /* Soma */
            reg[prog[pi+3]] = reg[prog[pi+1]] + reg[prog[pi+2]];
            pi+=4;
            break;
         case 11: /* Subtracao */
            reg[prog[pi+3]] = reg[prog[pi+1]] - reg[prog[pi+2]];
            pi+=4;
            break;
         case 12: /* Multiplicacao */
            reg[prog[pi+3]] = reg[prog[pi+1]] * reg[prog[pi+2]];
            pi+=4;
            break;
         case 13: /* Divisao */
            if (prog[pi+2] != 0) {
               reg[prog[pi+3]] = reg[prog[pi+1]] / reg[prog[pi+2]];
            } else {
               printf("ERRO DIVISAO POR ZERO");
               concluido = 1; /* Cancela execucao */
            }
            pi+=4;
            break;

         /******  LOGICOS  ******/
         
         case 20: /* Maior */
            e = reg[prog[pi+1]] > reg[prog[pi+2]];
            pi+=3;
            break;
         case 21: /* Menor */
            e = reg[prog[pi+1]] < reg[prog[pi+2]];
            pi+=3;
            break;
         case 22: /* Maior ou Igual */
            e = reg[prog[pi+1]] >= reg[prog[pi+2]];
            pi+=3;
            break;
         case 23: /* Menor ou Igual */
            e = reg[prog[pi+1]] <= reg[prog[pi+2]];
            pi+=3;
            break;
         case 24: /* Igual */
            e = reg[prog[pi+1]] = reg[prog[pi+2]];
            pi+=3;
            break;
         case 25: /* Diferente */
            e = reg[prog[pi+1]] != reg[prog[pi+2]];
            pi+=3;
            break;
         
         case 26: /* Negacao */
            reg[prog[pi+1]] = !reg[prog[pi+1]];
            pi+=2;
            break;
         case 27: /* Compara com 0 */
            e = reg[prog[pi+1]] == 0;
            pi+=2;
            break;

         /****** MOVIMENTACAO ******/

         case 30: /* Copia */
            reg[prog[pi+2]] = reg[prog[pi+1]];
            pi+=3;
            break;
         case 31: /* Troca */
            /*
               a = a - b;
               b = b + a;
               a = b - a;
            */
            reg[prog[pi+1]] = reg[prog[pi+1]] - reg[prog[pi+2]];
            reg[prog[pi+2]] = reg[prog[pi+2]] + reg[prog[pi+1]];
            reg[prog[pi+1]] = reg[prog[pi+2]] - reg[prog[pi+1]];
            pi+=3;
            break;

         case 32: /* Copia o valor de "e" */
            reg[prog[pi+1]] = e;
            pi+=2;
            break;
         case 33: /* Copia um valor em "e" */
            e = reg[prog[pi+1]];
            pi+=2;
            break;
         
         /******   DESVIOS   ******/
         
         case 40: /* pi += prog[pi] */
               pi += prog[pi+1];
            break;
         case 41: /*  // se E != 0 */
            if (e) {
               pi += prog[pi+1];
            } else {
               pi+=2;
            }
            break;
         case 42: /*  // se E = 0 */
            if (!e) {
               pi += prog[pi+1];
            } else {
               pi+=2;
            }
            break;

         /******  MISCELANEA  ******/
         
         case 50: /* Imprime um valor */
            printf("%lf\n", reg[prog[pi+1]]);            
            pi+=2;
               break;
         case 51: /* Le o valor da entrada */
            scanf("%lf", ®[prog[pi+1]]);
            pi+=2;
            break;
         case 52: /* Incrementa a variavel */
            ++reg[prog[pi+1]];
            pi+=2;
            break;
         case 53: /* Decrementa a variavel */
            --reg[prog[pi+1]];         
            pi+=2;
            break;
         case 54: /* NOVA: imprime um caracter */
            printf("%c", prog[pi+1]);            
            pi+=2;
            break;
         
         /******  MATEMATICOS  ******/         
         
         case 100: /* Raiz Quadrada */
            reg[prog[pi+2]] = sqrt(reg[prog[pi+1]]);
            pi+=3;
            break;
         case 101: /* Seno */
            reg[prog[pi+2]] = sin(reg[prog[pi+1]]);
            pi+=3;
            break;
         case 102: /* Cosseno */
            reg[prog[pi+2]] = cos(reg[prog[pi+1]]);
            pi+=3;
            break;
         case 103: /* Tangente */
            reg[prog[pi+2]] = tan(reg[prog[pi+1]]);
            pi+=3;
            break;
         
         /******    OUTROS    ******/
         
         case -1: /* Fim do programa */
            concluido = 1;
            break;

         
      } /* SWITCH */
         
    } /* WHILE */
      
   return 0;
      
}

Scripts recomendados

utilities_linux.h - Biblioteca com diversas funções para o Linux

Regra de Horner para cálculo do polinômio

Cadastro de alunos em C

média de notas de um aluno

Vários pacotes de ping disparados contra o host


  

Comentários
[1] Comentário enviado por SamL em 27/05/2010 - 13:23h

Legal, achei interessante esse programa, é quase como se "ganhasse vida".
Onde eu posso encontrar mais sobre o assunto?
Isso lembra muito uma FSM.
Valeu!


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts