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;
}
Servidor de Backup com Ubuntu Server 24.04 LTS, RAID e Duplicati (Dell PowerEdge T420)
Visualizar câmeras IP ONVIF no Linux sem necessidade de instalar aplicativos
Atualizar Debian Online de uma Versão para outra
Dica para encontrar diversos jogos Indies criativos
Instalando Discord no Debian 13
Instalar driver Nvidia no Debian 13
Redimensionando, espelhando, convertendo e rotacionando imagens com script
Software livre - será que eu estou tão errado assim? (10)
Boot do PosRog so funciona em notebook (1)