I am a web developer, trying to have fun with C++11, so any positive/negative feedback is very welcome.This is a toy virtual machine with 3 registers and 3 commands:vm/vm.h#ifndef VM_H#define VM_H#include <iostream>#include <vector>#include vtypes.hnamespace violet{    class Vm    {        bool running;        std::vector<u16> program;        u16  regs[REGS_N];        u16  pc;    public:        Vm(const std::vector<u16>);        ~Vm();        u16 fetch();        int run();        std::vector<u16> dump_regs() const;        instruction decode(const unsigned int) const;    };}#endif // VM_Hvm/vm.cpp#include vm.hnamespace violet{    Vm::Vm(const std::vector<u16> program):        running(false),        program(program),        pc(0)    {    }    Vm::~Vm()    {    }    u16 Vm::fetch()    {        return program.at(pc++);    }    int Vm::run()    {        running = true;        instruction instr;        if (program.empty()) return 1;        while(running && pc < program.size())        {            instr = decode(fetch());            switch(instr.code)            {                case i_halt:                    running = false;                    break;                case i_loadi:                    regs[instr.r0] = instr.imm;                    break;                case i_add:                    regs[instr.r0] = regs[instr.r1] + regs[instr.r2];                    break;            }        }        return 0;    }    std::vector<u16> Vm::dump_regs() const    {        return std::vector<u16>(std::begin(regs), std::end(regs));    }    instruction Vm::decode(const unsigned int opcode) const    {        instruction i;        // Bits 15-12  (4bits) Instruction number        // Bits 11-8   (4bits) Register number        // Bits 7-0    (8bits) Immediate value        i.code = (opcode & 0xF000) >> 12;        i.r0   = (opcode & 0xF00)  >>  8;        i.r1   = (opcode & 0xF0)   >>  4;        i.r2   = (opcode & 0xF);        i.imm  = (opcode & 0xFF);        return i;    }}vm/vtypes.h#ifndef VTYPES_H#define VTYPES_Husing u8  = unsigned char;    // At least 8-bitsusing u16 = unsigned short;   // At least 16-bits   -  (Usually)namespace violet{    const unsigned int REGS_N  {3};    // Instructions    const unsigned int i_halt  {0};    const unsigned int i_loadi {0x1};    const unsigned int i_add   {0x2};    struct instruction    {        unsigned int code;        unsigned int r0;        unsigned int r1;        unsigned int r2;        int imm;    };}#endif // VTYPES_Hvm/main.cpp#include <vector>#include vm/vm.h#include etc/utils.husing namespace violet;int main(int argc, char *argv[]){    int vm_res;    const std::vector<u16> program = utils::load_program_file(argv[1]);    Vm vm(program);    vm_res = vm.run();    for (auto r : vm.dump_regs())    {        std::cout << r <<  ;    }   std::cout << std::endl;    return vm_res;}asm/vlasm.h#ifndef VLASM_H#define VLASM_H#include <vector>#include <string>#include <unordered_map>#include vm/vtypes.hnamespace violet{    namespace vlasm    {        const char comment(';');        const std::string i_halt(halt);        const std::string i_loadi(loadi);        const std::string i_add(add);        const std::unordered_map<std::string, unsigned int>        registers {                {r0, 0},                {r1, 1},                {r2, 2}        };        std::vector<unsigned int> parse_source(const std::vector<std::string>);        std::vector<std::string> parse_line(const std::string);        unsigned int parse_tokens(const std::vector<std::string>);        unsigned int parse_reg(const std::string);        void die(const char *);    };}#endif // VLASM_Hasm/vlasm.cpp#include <sstream>#include <iostream>#include <iterator>#include vlasm.hnamespace violet{    namespace vlasm    {        std::vector<unsigned int>        parse_source(const std::vector<std::string> source)        {            std::vector<unsigned int> program;            for (auto line : source)            {                if (line[0] == comment) continue;                std::vector<std::string> tokens = parse_line(line);                program.push_back(parse_tokens(tokens));            }            return program;        }        std::vector<std::string>        parse_line(const std::string line)        {            std::istringstream iss(line);            std::vector<std::string> tokens {                    std::istream_iterator<std::string>{iss},                    std::istream_iterator<std::string>{}            };            return tokens;        }        unsigned int parse_tokens(const std::vector<std::string> tokens)        {            unsigned int opcode;            if (tokens[0] == vlasm::i_halt)            {               opcode = violet::i_halt;            }            else if (tokens[0] == vlasm::i_loadi)            {                if (tokens.size() != 3) die(Invalid load operation);                opcode = (violet::i_loadi      << 12) |                         (parse_reg(tokens[1]) <<  8) |                          std::stoi(tokens[2]) ;            }            else if (tokens[0] == vlasm::i_add)            {                if (tokens.size() != 4) die(Invalid addition operation);                opcode = (violet::i_add << 12) |                         (parse_reg(tokens[1]) << 8) |                         (parse_reg(tokens[2]) << 4) |                          parse_reg(tokens[3]);            }            else            {                die(Invalid instruction found);            }            return opcode;        }        unsigned int parse_reg(std::string reg_str)        {            std::unordered_map<std::string, unsigned int>::const_iterator            r = registers.find(reg_str);            if (r == registers.end()) die(Invalid register);            return r->second;        }        void die(const char *message)        {            std::cerr << message << std::endl;            exit(1);        }    }}asm/main.cpp#include <vector>#include <etc/utils.h>#include vlasm.husing namespace violet;int main(int argc, char *argv[]){    const std::vector<std::string> source = utils::load_source_file(argv[1]);    const std::vector<unsigned int> program = vlasm::parse_source(source);    return utils::write_program_file(argv[2], program);}etc/utils.h#ifndef UTILS_H#define UTILS_H#include <iostream>#include <vector>#include <string>#include <fstream>#include vm/vtypes.h    namespace violet    {        namespace utils        {            std::vector<u16> load_program_file(const std::string);            std::vector<std::string> load_source_file(const std::string);            int write_program_file(const std::string, const std::vector<unsigned int>);        }    };    #endif // UTILS_Hetc/utils.cpp#include utils.hnamespace violet{    namespace utils    {        std::vector<u16>        load_program_file(const std::string filename)        {            u16 instr;            u8  bytes[2];            std::vector<u16> result;            std::ifstream file(filename, std::ios::binary);            if (file.fail())            {                std::cerr << Could not load program << std::endl;                return result;            }            while(file.read(reinterpret_cast<char*>(bytes), 2))            {                // Little endian                instr = bytes[0] | bytes[1] << 8;                result.push_back(instr);            }            return result;        }        std::vector<std::string>        load_source_file(const std::string filename)        {            std::string line;            std::vector<std::string> result;            std::ifstream file(filename);            if (file.fail())            {                std::cerr << Could not load source << std::endl;                return result;            }            while(std::getline(file, line))            {                result.push_back(line);            }            return result;        }        int write_program_file(                const std::string filename,                const std::vector<unsigned int> program)        {            std::ofstream out(filename, std::ios::trunc | std::ios::binary);            if (out.fail())            {                std::cerr << Could not write program file << std::endl;                return 1;            }            for (auto i : program)            {                out.write(reinterpret_cast<const char *>(&i), sizeof(u16));            }            return 0;        }    }}Usage:$ violet /path/to/bin.s$ vlasm /path/to/source.vl /path/to/bin.sAsm syntax:loadi [reg][val] - load immediate value([val]) to register([reg])   add [reg1][reg2][reg3] - place the sum of [reg2] and [reg3] into [reg1] halt - stop the executionExample program; comments start with semicolonloadi r0 100loadi r1 200add r2 r0 r1; now r2 holds the value 300haltThis program compiled to vm bytecode:  6410 c811 0122 0000  
Toy virtual machine
c++;c++11