Skip to content

Instantly share code, notes, and snippets.

@flisboac
Last active November 28, 2015 23:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flisboac/feb4b3c6cd459b8b2182 to your computer and use it in GitHub Desktop.
Save flisboac/feb4b3c6cd459b8b2182 to your computer and use it in GitHub Desktop.
Uma máquina virtual bem simples...
SET 1 2
SET 2 5
MUL 1 2 3
SET 4 2
ADD 3 4 5
SET 6 2
DIV 5 6 7
SET 8 4
SUB 7 8 9
PRL 9
DMP
END
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
// 256 bytes de memória volátil endereçável
// 256 registradores de inteiros
// 256 bytes de programa
public class Vm {
public static final int FINALIZADO = -1;
public static final int NAO_INICIADO = -2;
public static enum Opcode {
END(0, "END", 0),
ADD(1, "ADD", 3),
SUB(2, "SUB", 3),
MUL(3, "MUL", 3),
DIV(4, "DIV", 3),
SET(5, "SET", 2),
PRL(6, "PRL", 1),
DMP(7, "DMP", 0); // DUMP de memoria e registros
public final int valor;
public final String mnemonico;
public final int numeroArgumentos;
private Opcode(int valor, String mnemonico, int numeroArgumentos) {
this.valor = valor;
this.mnemonico = mnemonico;
this.numeroArgumentos = numeroArgumentos;
}
public static Opcode buscarPorMnemonico(String mnemonico) {
Opcode opcode = null;
if (mnemonico != null) {
for (Opcode elem : values()) {
if (elem.mnemonico.compareToIgnoreCase(mnemonico) == 0) {
opcode = elem;
break;
}
}
}
return opcode;
}
public static Opcode buscarPorValor(int valor) {
Opcode opcode = null;
for (Opcode elem : values()) {
if (elem.valor == valor) {
opcode = elem;
break;
}
}
return opcode;
}
}
public static class Instrucao {
public final Opcode opcode;
public final Integer[] argumentos;
public Instrucao() {
this.opcode = null;
this.argumentos = new Integer[0];
}
public Instrucao(Opcode opcode) {
this.opcode = opcode;
this.argumentos = new Integer[0];
}
public Instrucao(Opcode opcode, Integer... argumentos) {
this.opcode = opcode;
this.argumentos = argumentos;
if (argumentos.length != opcode.numeroArgumentos) {
throw new IllegalArgumentException(
opcode.mnemonico + " deve possuir "
+ opcode.numeroArgumentos + " argumentos.");
}
}
}
private List<Instrucao> programa = new ArrayList<>();
private int[] registradores = new int[16];
private int pc = NAO_INICIADO;
private boolean finalizado;
public void lerPrograma(InputStream stream) {
Opcode opcode = null;
Scanner scanner = new Scanner(stream);
String regex = "[^\\s]+";
while (scanner.hasNext()) {
if (opcode == null) {
String valor = scanner.next();
opcode = Opcode.buscarPorMnemonico(valor);
// OPCODE invalido
if (opcode == null) {
throw new UnsupportedOperationException("Mnemônico " + valor + " inválido.");
} else {
//System.err.println("** Encontrado Mnemonico: " + valor);
}
// Caso o opcode nao receba argumentos, a leitura do arquivo nao
// precisa continuar a buscar argumentos; sendo assim, a rotina
// nao vai executar o else deste if.
// Neste caso, deve-se adicionar o opcode de imediato.
if (opcode.numeroArgumentos == 0) {
programa.add(new Instrucao(opcode));
opcode = null;
}
} else {
// Pegar o número de argumentos necessários
Integer[] argumentos = new Integer[opcode.numeroArgumentos];
for (int numeroArgumento = 0; numeroArgumento < opcode.numeroArgumentos; numeroArgumento++) {
int argumento = scanner.nextInt();
//System.err.println("*** " + opcode.mnemonico + " ARG[" + numeroArgumento + "] = " + argumento);
argumentos[numeroArgumento] = argumento;
}
programa.add(new Instrucao(opcode, argumentos));
opcode = null;
}
}
}
// "dispatcher"
public void executarInstrucao(Instrucao instrucao) {
int r1, r2, r3, v;
switch (instrucao.opcode) {
case END:
this.finalizado = true;
//System.err.println("*** FINALIZADO! this.pc == " + this.pc);
break;
case ADD:
// ADD R1 R2 R3 -> R3 = R1 + R2
r1 = instrucao.argumentos[0];
r2 = instrucao.argumentos[1];
r3 = instrucao.argumentos[2];
this.registradores[r3] = this.registradores[r1] + this.registradores[r2];
break;
case SUB:
r1 = instrucao.argumentos[0];
r2 = instrucao.argumentos[1];
r3 = instrucao.argumentos[2];
this.registradores[r3] = this.registradores[r1] - this.registradores[r2];
break;
case MUL:
r1 = instrucao.argumentos[0];
r2 = instrucao.argumentos[1];
r3 = instrucao.argumentos[2];
this.registradores[r3] = this.registradores[r1] * this.registradores[r2];
break;
case DIV:
r1 = instrucao.argumentos[0];
r2 = instrucao.argumentos[1];
r3 = instrucao.argumentos[2];
this.registradores[r3] = this.registradores[r1] / this.registradores[r2];
break;
case SET:
// SET R1 V -> R1 = V
r1 = instrucao.argumentos[0];
v = instrucao.argumentos[1];
this.registradores[r1] = v;
break;
case PRL:
r1 = instrucao.argumentos[0];
System.out.println(this.registradores[r1]);
break;
case DMP:
System.out.println("- PC = " + this.pc);
for (int i = 0; i < this.registradores.length; i++) {
System.out.println("- R[" + i + "] = " + this.registradores[i]);
}
for (int i = 0; i < this.programa.size(); i++) {
Instrucao instrucaoExibicao = this.programa.get(i);
Integer[] argumentos = instrucaoExibicao.argumentos;
Opcode opcode = instrucaoExibicao.opcode;
String texto = "- I[" + i + "]: " + opcode.mnemonico;
String sep = " ";
for (int indiceArgumento = 0; indiceArgumento < argumentos.length; indiceArgumento++) {
texto += sep + argumentos[indiceArgumento];
sep = " ";
}
System.out.println(texto);
}
break;
}
}
public void continuar() {
Instrucao instrucao = this.programa.get(this.pc);
executarInstrucao(instrucao);
incrementarContador();
}
private void incrementarContador() {
this.pc++;
}
public boolean isFinalizado() {
return this.finalizado;
}
public boolean isIniciado() {
return this.pc > NAO_INICIADO;
}
public void iniciar() {
this.pc = 0;
}
public void executar() {
if (!isIniciado()) {
iniciar();
}
while (!isFinalizado()) {
continuar();
}
}
public static void main(String[] args) throws FileNotFoundException {
InputStream stream;
if (args.length == 0) {
stream = new BufferedInputStream(System.in);
} else {
File arquivo = new File(args[0]);
stream = new BufferedInputStream(new FileInputStream(arquivo));
}
Vm vm = new Vm();
vm.lerPrograma(stream);
vm.executar();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment