Máquina virtual
Publicado por Gabriel (última atualização em 25/05/2010)
[ Hits: 8.900 ]
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;
}
Jogo da Velha contra o Computador.
Balanceamento de parênteses utilizando Pilha
IA Turbina o Desktop Linux enquanto distros renovam forças
Como extrair chaves TOTP 2FA a partir de QRCODE (Google Authenticator)
Linux em 2025: Segurança prática para o usuário
Desktop Linux em alta: novos apps, distros e privacidade marcam o sábado
IA chega ao desktop e impulsiona produtividade no mundo Linux
Atualizando o Fedora 42 para 43
Como saber se o seu e-mail já teve a senha vazada?
Como descobrir se a sua senha já foi vazada na internet?
Mint Xfce não mantém a conexão no wi-fi (2)
Problemas com Driver NVIDIA (5)
Warcraft II Remastered no Linux? (8)









