Enviado em 18/02/2016 - 20:08h
Olá !!!
OP_HALT
OP_NOP
OP_PUSH_LONG
OP_PUSH_FLOAT
OP_PUSH_VAR
OP_SET_VAR
OP_INC
OP_PRINT
/*
**-------------------------------------------------------------------
**
** Simples VM:
**
** COMPILE:
** gcc vm.c -o vm -O2 -Wall
** ou
** g++ vm.c -o vm -O2 -Wall
**
**-------------------------------------------------------------------
*/
#include <stdio.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;
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
};
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;
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;
sp = stack;
return;
}
if (!vm)
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+2);
} 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;
}
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->pos = 0;
}
return vm;
}
//-------------------------------------------------------------------
//########################### gen/emit ############################
//-------------------------------------------------------------------
//
void g_halt (VM *vm)
{
vm->code[vm->pos++].jmp = Gtable [ OP_HALT ];
}
void g_nop (VM *vm)
{
vm->code[vm->pos++].jmp = Gtable [ OP_NOP ];
}
void g_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+2) = value;
vm->pos++;
}
void g_inc (VM *vm, int index)
{
vm->code[vm->pos].jmp = Gtable [ OP_INC ];
vm->code[vm->pos].arg.l = index;
vm->pos++;
}
void g_print (VM *vm, int index)
{
vm->code[vm->pos].jmp = Gtable [ OP_PRINT ];
vm->code[vm->pos].arg.l = index;
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 *******
//-------------------------
//
g_set_var (vm, 10, 1500); // seta ( Gvar[10].arg.l ) com o valor 1500
g_inc (vm, 10); // incrementa ( Gvar[10].arg.l )
g_print (vm, 10); // imprime ( Gvar[10].arg.l ) ... 1501
g_halt (vm); // o OPCODE mais importante para sair da VM
vm_run (vm); // agora executa a VM
// aqui: falta liberar memoria ... fica para a proxima
// ...
}
printf ("Saindo Com Sucesso !!!\n");
return 0;
}
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
Aplicativo simples para gravar tela
Quebra de linha na data e hora no Linux Mint
Como fazer boot em img do debian 12.img da web? (7)
Manjaro 25.0 no permite usar crontab (1)
trocar linhas [RESOLVIDO] (11)