Máquina virtual
Publicado por Gabriel (última atualização em 25/05/2010)
[ Hits: 8.976 ]
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.
/*******************************************************************/
/** **/
/** 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;
}
utilities_linux.h - Biblioteca com diversas funções para o Linux
Shadow Mapping utilizando OpenGL e Cg
Alocando espaço para uma matriz dinamicamente
Cirurgia para acelerar o openSUSE em HD externo via USB
Void Server como Domain Control
Modo Simples de Baixar e Usar o bash-completion
Monitorando o Preço do Bitcoin ou sua Cripto Favorita em Tempo Real com um Widget Flutuante
Como impedir exclusão de arquivos por outros usuários no (Linux)
Cirurgia no Linux Mint em HD Externo via USB
Anúncio do meu script de Pós-Instalação do Ubuntu
Formas seguras de instalar Debian Sid (2)
Duas Pasta Pessoal Aparecendo no Ubuntu 24.04.3 LTS (12)
Alguém pode me indicar um designer freelancer? [RESOLVIDO] (5)
Alguém executou um rm e quase mata a Pixar! (3)
Por que passar nas disciplinas da faculdade é ruim e ser reprovado é b... (6)









