Máquina virtual
Publicado por Gabriel (última atualização em 25/05/2010)
[ Hits: 8.550 ]
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; }
[C] Decompositor de números em fatores primos
Contagem de elementos de um array
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Como renomear arquivos de letras maiúsculas para minúsculas
Imprimindo no formato livreto no Linux
Vim - incrementando números em substituição
Efeito "livro" em arquivos PDF
Como resolver o erro no CUPS: Unable to get list of printer drivers
Não to conseguindo resolver este problemas ao instalar o playonelinux (1)
Excluir banco de dados no xampp (1)
[Python] Automação de scan de vulnerabilidades
[Python] Script para analise de superficie de ataque
[Shell Script] Novo script para redimensionar, rotacionar, converter e espelhar arquivos de imagem
[Shell Script] Iniciador de DOOM (DSDA-DOOM, Doom Retro ou Woof!)
[Shell Script] Script para adicionar bordas às imagens de uma pasta