Máquina virtual
Publicado por Gabriel (última atualização em 25/05/2010)
[ Hits: 8.625 ]
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; }
Teste de desempenho com números primos em C
MeikeNeime - Programa gerador de nomes aleatórios
Passkeys: A Evolução da Autenticação Digital
Instalação de distro Linux em computadores, netbooks, etc, em rede com o Clonezilla
Título: Descobrindo o IP externo da VPN no Linux
Armazenando a senha de sua carteira Bitcoin de forma segura no Linux
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Instalando Brave Browser no Linux Mint 22
vídeo pra quem quer saber como funciona Proteção de Memória:
Encontre seus arquivos facilmente com o Drill
Mouse Logitech MX Ergo Advanced Wireless Trackball no Linux
Compartilhamento de Rede com samba em modo Público/Anônimo de forma simples, rápido e fácil
PC não liga no filtro de linha (5)
Remoção de propaganda com o programa Comskip[AJUDA] (5)
Linux Lite Demorando Muito Para Ligar (2)