Máquina virtual
Publicado por Gabriel (última atualização em 25/05/2010)
[ Hits: 8.786 ]
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; }
Sintetizador sonoro que toca redez vouz 4
Conio.h para Linux (Nova versão)
Atualizando o Passado: Linux no Lenovo G460 em 2025
aaPanel - Um Painel de Hospedagem Gratuito e Poderoso
O macete do Warsaw no Linux Mint e cia
Um modo leve de ouvir/ver áudio/vídeo da internet em máquinas pererecas
Resolver algumas mensagens de erro do SSH
Instalar módulo de segurança do Banco do Brasil Warsaw do tipo .run
Sem espaço na partição home (0)
O que você está ouvindo agora? [2] (190)
Procrastinação e autossabotagem são problemas muito comuns na sociedad... (5)
warsaw parou de funcionar após atualização do sistema (solução) (10)