Skip to content

Instantly share code, notes, and snippets.

@hogelog
Created September 7, 2010 06:05
Show Gist options
  • Save hogelog/567934 to your computer and use it in GitHub Desktop.
Save hogelog/567934 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <stack>
#define MEMSIZE 30000
#define CODESIZE 30000
#include "xbyak/xbyak.h"
class BFVM : public Xbyak::CodeGenerator {
private:
std::istream& input;
int membuf[MEMSIZE];
static const char* toLabel(char ch, int num)
{
static std::stringstream labelStream;
labelStream.str("");
labelStream << ch << num;
return labelStream.str().c_str();
}
public:
BFVM(std::istream& input) :
CodeGenerator(CODESIZE),
input(input)
{
using namespace Xbyak;
push(ebx);
Reg32 mem(ebx);
mov(mem, (int) membuf);
char ch = 0;
std::stack<int> labelStack;
int labelNum = 0;
std::string label;
while(input.get(ch).good()) {
switch(ch) {
case '+':
mov(eax, ptr[mem]);
inc(eax);
mov(ptr[mem], eax);
break;
case '-':
mov(eax, ptr[mem]);
dec(eax);
mov(ptr[mem], eax);
break;
case '>':
add(mem, 4);
break;
case '<':
add(mem, -4);
break;
case ',':
call((void*) getchar);
mov(ptr[mem], eax);
break;
case '.':
push(ptr[mem]);
call((void*) putchar);
add(esp, 4);
break;
case '[':
L(toLabel('L', labelNum));
mov(eax, ptr[mem]);
test(eax, eax);
jz(toLabel('R', labelNum), T_NEAR);
labelStack.push(labelNum);
++labelNum;
break;
case ']':
int beginNum = labelStack.top();
labelStack.pop();
jmp(toLabel('L', beginNum), T_NEAR);
L(toLabel('R', beginNum));
break;
}
}
pop(ebx);
ret();
}
void execute()
{
void (*codes)() = (void (*)()) getCode();
codes();
}
};
int main()
{
BFVM bf(std::cin);
bf.execute();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment