
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;
}
Cirurgia para acelerar o openSUSE em HD externo via USB
Void Server como Domain Control
Modo Simples de Baixar e Usar o bash-completion
Monitorando o Preço do Bitcoin ou sua Cripto Favorita em Tempo Real com um Widget Flutuante
[Resolvido] VirtualBox can't enable the AMD-V extension
Como verificar a saúde dos discos no Linux
Como instalar , particionar, formatar e montar um HD adicional no Linux?
Como automatizar sua instalação do Ubuntu para desenvolvimento de software.
Fiz uma pergunta no fórum mas não consigo localizar (18)
Não consigo instalar distro antiga no virtualbox nem direto no hd (9)
Quais os códigos mais dificeis que vcs sabem fazer? (5)
Upscaling com imagem cortada no monitor secundário ao usar iGPU Multi ... (1)
Servidor Ubuntu 24.04 HD 500 não tenho espaço na \home\adminis... [RES... (8)









