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;
}
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
Efeito "livro" em arquivos PDF
Como resolver o erro no CUPS: Unable to get list of printer drivers
Flatpak: remover runtimes não usados e pacotes
Mudar o gerenciador de login (GDM para SDDM e vice-versa) - parte 2
instalação de SQL SERVER LICENCIADO (1)
Modernização e Avanço do Linux. (3)
[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