Máquina virtual
Publicado por Gabriel (última atualização em 25/05/2010)
[ Hits: 8.754 ]
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; }
Vários pacotes de ping disparados contra o host
Decimal, Hexa, Char para Binário
Aprenda a Gerenciar Permissões de Arquivos no Linux
Como transformar um áudio em vídeo com efeito de forma de onda (wave form)
Como aprovar Pull Requests em seu repositório Github via linha de comando
Mantenha seu Sistema Leve e Rápido com a Limpeza do APT!
Procurando vídeos de YouTube pelo terminal e assistindo via mpv (2025)
Gravação de tela com temporizador
Usar uma VM dentro do meu notebook como firewall para um dispositivo e... (0)
Eu tive esse erro aqui depois de de baixar o HyprLand Ubuntu na versão... (1)
Como fazer boot em img do debian 12.img da web? (11)