function b2d(binary) {
  var b = binary.reverse();
  var d = 0;
  for(var i=0;i<b.length;++i) {
    d += b[i]*Math.pow(2,i);
  }
  return d;
}

function Register32(name, mask) {
  this.name = name;
  this.mask = mask;
  return this;
}

var EAX = new Register32("EAX", [0,0,0]);
var ECX = new Register32("ECX", [0,0,1]);
var EDX = new Register32("EDX", [0,1,0]);
var EBX = new Register32("EBX", [0,1,1]); 
var ESP = new Register32("ESP", [1,0,0]);
var EBP = new Register32("EBP", [1,0,1]);
var ESI = new Register32("ESI", [1,1,0]);
var EDI = new Register32("EDI", [1,1,1]);

function X86Assembler(image) {
  this.image = image;
  return this;
}

X86Assembler.prototype.label = function(name) {
  this.image.label(name);
  return this;
}

X86Assembler.prototype.move = function(value, register) {
  var image = this.image;
  // MOV r32,imm32
  image.emit(b2d([1,1,0,0,0,1,1,1]));
  image.emit(b2d([1,1,0,0,0].concat(register.mask)))
  image.emit32(value);
  return this;
}

X86Assembler.prototype.jmpNear = function(label) {
  var image = this.image;
  // JMP short, relative to next instruction
  image.emit(b2d([1,1,1,0,1,0,1,1]));
  image.referLabel(label);
  image.emit(0)
  return this;
}


X86Assembler.prototype.adc = function(r1, r2) {
  var image = this.image;
  // MOV r32,imm32
  image.emit(b2d([0,0,0,1,0,0,0,1]));
  image.emit(b2d([1,1].concat(r1.mask).concat(r2.mask)))
  return this;
}

X86Assembler.prototype.ret = function() {
  var image = this.image;
  // near return to calling procedure
  image.emit(b2d([1,1,0,0,0,0,1,1]));
  return this;
}

