codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
/* **------------------------------------------------------------------- ** ** Simples VM: ** ** COMPILE 32 BITS: ** gcc vm.c -o vm -O2 -Wall -m32 ** ou ** g++ vm.c -o vm -O2 -Wall -m32 ** ** COMPILE 64 BITS: ** gcc vm.c -o vm -O2 -Wall -m64 ** ou ** g++ vm.c -o vm -O2 -Wall -m64 ** **------------------------------------------------------------------- */ #include <stdio.h> #include <string.h> #include <stdlib.h> #define NEXT goto *(++vm->ip)->jmp #define GTABLE_SIZE 255 #define GVAR_SIZE 255 #define STACK_SIZE 1024 typedef struct VM VM; typedef union VALUE VALUE; typedef struct VAR VAR; typedef struct OPCODE OPCODE; typedef struct LABEL LABEL; struct VM { OPCODE *ip; OPCODE *code; LABEL *label; LABEL *jump; int pos; }; union VALUE { long l; float f; char *s; void *p; }; struct VAR { char *name; int type; VALUE value; }; struct OPCODE { void *jmp; VALUE arg; // argumento 1 }; struct LABEL { char *text; int pos; LABEL *next; }; enum { // opcodes: OP_HALT = 0, // para sair da VM OP_NOP, // no opcode OP_PUSH_LONG, // da um "push" ... e seta o topo da pilha ( *sp ) com um valor long OP_PUSH_FLOAT, // da um "push" ... e seta o topo da pilha ( *sp ) com um valor float OP_PUSH_VAR, // da um "push" ... e seta o topo da pilha ( *sp ) com uma variavel //------------------------------------------- // OBS: Essa instrucao utiliza 2 argumentos: // 1: short = o index de Gvar [ ] // 2: long = o valor da variavel //------------------------------------------- OP_SET_VAR, // seta um valor de uma variavel ... somente tipo long OP_INC, // incrementa uma variavel ( Gvar[] ) OP_PRINT, // imprime o valor de uma variavel OP_CMP_LONG, // compara 2 valores tipo long , seta (flag_long) e da 2 "pop" OP_JMP, // pula para um opcode OP_JG }; void *Gtable [ GTABLE_SIZE ]; VAR Gvar [ GVAR_SIZE ]; VALUE stack [ STACK_SIZE ]; // a pilha base VALUE *sp; // o topo da pilha int flag_long; float flag_float; int count; void vm_run (VM *vm) { if (Gtable[0] == NULL) { Gtable [ OP_HALT ] = && op_halt; Gtable [ OP_NOP ] = && op_nop; Gtable [ OP_PUSH_LONG ] = && op_push_long; Gtable [ OP_PUSH_FLOAT ] = && op_push_float; Gtable [ OP_PUSH_VAR ] = && op_push_var; Gtable [ OP_SET_VAR ] = && op_set_var; Gtable [ OP_INC ] = && op_inc; Gtable [ OP_PRINT ] = && op_print; Gtable [ OP_CMP_LONG ] = && op_cmp_long; Gtable [ OP_JMP ] = && op_jmp; Gtable [ OP_JG ] = && op_jg; sp = stack; return; } if (vm==NULL) return; vm->ip = vm->code; goto *vm->ip->jmp; // pula para a primeira "inctrucao" //--------------------------------------------- //########## OPCODES implementacao ########## //--------------------------------------------- // op_halt: printf ("Instrucao OP_HALT ... saindo da VM\n"); return; op_nop: // sem opcode ... NEXT; op_push_long: { sp++; sp->l = vm->ip->arg.l; } NEXT; op_push_float: { sp++; sp->f = vm->ip->arg.f; } NEXT; op_push_var: { sp++; // somente tipo long por enquanto sp->l = Gvar [ vm->ip->arg.l ].value.l; } NEXT; op_set_var: { // somente tipo long por enquanto Gvar [ *(short*)vm->ip->arg.s ].value.l = *(long*)(vm->ip->arg.s+sizeof(short)); } NEXT; op_inc: { // somente tipo long por enquanto Gvar [ vm->ip->arg.l ].value.l++; } NEXT; op_print: { // somente tipo long por enquanto printf ("Gvar[ %ld ] = %ld\n", vm->ip->arg.l, Gvar [ vm->ip->arg.l ].value.l); } NEXT; op_cmp_long: { flag_long = (sp-1)->l - (sp)->l; sp -= 2; // pop 2 } NEXT; op_jmp: { goto *(vm->ip = vm->code + vm->ip->arg.l)->jmp; } op_jg: { if (flag_long > 0) { goto *(vm->ip = vm->code + vm->ip->arg.l)->jmp; } } NEXT; }//: vm_run () VM *vm_new (int size) { VM *vm = (VM*) malloc (sizeof(VM)); if (vm) { if ( (vm->code = (OPCODE*) malloc (sizeof(OPCODE)*size)) == NULL) return NULL; vm->ip = vm->code; vm->label = NULL; vm->jump = NULL; vm->pos = 0; } return vm; } void vm_label (VM *vm, char *text) { LABEL *n; if (!text) return; // verifica se ja existe ... entao sai n = vm->label; while (n) { if (!strcmp(n->text, text)) { printf ("Label ja existe(%s)\n", text); return; } n = n->next; } n = (LABEL*) malloc (sizeof(LABEL)); if (n && text) { n->text = strdup (text); n->pos = vm->pos; // add on top n->next = vm->label; vm->label = n; } } void vm_new_jump (VM *vm, char *text) { LABEL *n = (LABEL*) malloc (sizeof(LABEL)); if (n && text) { n->text = strdup (text); n->pos = vm->pos; // add on top n->next = vm->jump; vm->jump = n; } } void vm_resolve_jump (VM *vm) { LABEL *label, *jump; label = vm->label; while (label) { jump = vm->jump; while (jump) { if (!strcmp(label->text, jump->text)) { // muda aqui: vm->code[ jump->pos ].arg.l = label->pos; } jump = jump->next; } label = label->next; } } void vm_free (VM *vm) { int i; LABEL *temp; // libera: o "OPCODE"(OP_SET_VAR) que eh um string for (i=0;i<vm->pos;i++) if (vm->code[i].jmp == Gtable [OP_SET_VAR] && vm->code[i].arg.s != NULL) { free (vm->code[i].arg.s); vm->code[i].arg.s = NULL; } // libera: o label while (vm->label != NULL) { temp = vm->label->next; if (vm->label->text) free(vm->label->text); free (vm->label); vm->label = temp; } // libera: o jump while (vm->jump != NULL) { temp = vm->jump->next; if (vm->jump->text) free(vm->jump->text); free (vm->jump); vm->jump = temp; } free (vm->code); free (vm); } //------------------------------------------------------------------- //########################### gen/emit ############################ //------------------------------------------------------------------- // void gen_halt (VM *vm) { vm->code[vm->pos++].jmp = Gtable [ OP_HALT ]; } void gen_nop (VM *vm) { vm->code[vm->pos++].jmp = Gtable [ OP_NOP ]; } void gen_push_long (VM *vm, long value) { vm->code[vm->pos].jmp = Gtable [ OP_PUSH_LONG ]; vm->code[vm->pos].arg.l = value; vm->pos++; } void gen_push_float (VM *vm, float value) { vm->code[vm->pos].jmp = Gtable [ OP_PUSH_FLOAT ]; vm->code[vm->pos].arg.f = value; vm->pos++; } void gen_push_var (VM *vm, int index) { vm->code[vm->pos].jmp = Gtable [ OP_PUSH_VAR ]; vm->code[vm->pos].arg.l = index; vm->pos++; } void gen_set_var (VM *vm, short index, long value) { vm->code[vm->pos].jmp = Gtable [ OP_SET_VAR ]; vm->code[vm->pos].arg.s = (char*)malloc ((sizeof(short)+sizeof(long))+1); *(short*)(vm->code[vm->pos].arg.s) = index; *(long*)(vm->code[vm->pos].arg.s+sizeof(short)) = value; vm->pos++; } void gen_inc (VM *vm, int index) { vm->code[vm->pos].jmp = Gtable [ OP_INC ]; vm->code[vm->pos].arg.l = index; vm->pos++; } void gen_print (VM *vm, int index) { vm->code[vm->pos].jmp = Gtable [ OP_PRINT ]; vm->code[vm->pos].arg.l = index; vm->pos++; } void gen_cmp_long (VM *vm) { vm->code[vm->pos].jmp = Gtable [ OP_CMP_LONG ]; vm->pos++; } void gen_jmp (VM *vm, char *text) { vm->code[vm->pos].jmp = Gtable [ OP_JMP ]; vm->code[vm->pos].arg.l = vm->pos; vm_new_jump (vm, text); vm->pos++; } void gen_jg (VM *vm, char *text) { vm->code[vm->pos].jmp = Gtable [ OP_JG ]; vm->code[vm->pos].arg.l = vm->pos; vm_new_jump (vm, text); vm->pos++; } int main (int argc, char *argv[]) { VM *vm; //----------------------------------------- // cria uma VM com maximo de 100 instrucoes //----------------------------------------- // if ((vm = vm_new(100)) != NULL) { vm_run (NULL); // setup Gtable [ ] //------------------------- //####### gen/emit ####### //------------------------- // // CODIGO SIMILAR C: // // for (i = 100; i < 150; i++) printf("i: %d\n", i); // gen_set_var (vm, 10, 100); // seta ( Gvar[10].arg.l ) com o valor 100 vm_label (vm, "loop_inicio"); gen_push_var (vm, 10); gen_push_long (vm, 150-1); gen_cmp_long (vm); // compara 2 valores gen_jg (vm, "loop_fim"); // pula para o fim do loop se ( flag_long > 0 ) //######### o bloco do loop: ######## gen_print (vm, 10); // imprime ( Gvar[10].arg.l ) gen_inc (vm, 10); // incrementa ( Gvar[10].arg.l ) //################################### gen_jmp (vm, "loop_inicio"); // pula para o inicio do loop. vm_label (vm, "loop_fim"); gen_halt (vm); // o OPCODE mais importante para sair da VM //######################### vm_resolve_jump (vm); // muda as posicoes dos "jumps" vm_run (vm); // agora executa a VM vm_free (vm); // libera a memoria } printf ("Saindo Com Sucesso !!!n"); return 0; }
Private
[
?
]
Run code
Submit