module Wilson

Wilson is a pure ruby x86 assembler. No, really. Worst Idea Evar.

Why “wilson”? I wanted to name it “metal”, but there is an existing project with that name… So I'm naming it after Wilson Bilkovich, who is about as metal as you can get (and it is easier to spell than “bilkovich”, even tho that sounds more metal).

Wilson is a port (and extension) of the smalltalk x86 assembler by Michael Lucas-Smith. I came across it when he presented it at Smalltalk SuperPowers at OOPSLA 2008.

Constants

VERSION

Public Class Methods

commands() click to toggle source
# File lib/wilson.rb, line 88
def self.commands
  self.default.commands
end
default() click to toggle source
# File lib/wilson.rb, line 80
def self.default
  @@default ||= self.new.parse
end
default=(o) click to toggle source
# File lib/wilson.rb, line 84
def self.default= o
  @@default = o
end
new() click to toggle source
# File lib/wilson.rb, line 96
def initialize
  self.commands = []
end
parse() click to toggle source
# File lib/wilson.rb, line 92
def self.parse
  self.new.parse
end

Public Instance Methods

add_command(command) click to toggle source
# File lib/wilson.rb, line 140
def add_command command
  return self.add_conditional_commands(command) if command.opcode =~ /cc$/i
  self.commands << command
  self.expand_parameters command
end
add_conditional_commands(prototype) click to toggle source
# File lib/wilson.rb, line 118
def add_conditional_commands prototype
  prototype.opcode = prototype.opcode[0..-3]

  self.conditionals.each do |conditional, value|
    command = prototype.dup
    command.opcode += conditional

    command.opcodes.each_with_index do |op, index|
      command.opcodes[index] = ($1.hex+value).to_s(16) if op =~ /(.*)\+cc$/
    end

    self.add_command command
  end
end
conditionals() click to toggle source
# File lib/wilson.rb, line 146
def conditionals
  @conditionals ||= {
    'O'   =>  0, 'NO' =>  1, 'B'  =>  2, 'C'   =>  2, 'NAE' =>  2,
    'AE'  =>  3, 'NB' =>  3, 'NC' =>  3, 'E'   =>  4, 'Z'   =>  4,
    'NE'  =>  5, 'NZ' =>  5, 'BE' =>  6, 'NA'  =>  6, 'A'   =>  7,
    'NBE' =>  7, 'S'  =>  8, 'NS' =>  9, 'P'   => 10, 'PE'  => 10,
    'NP'  => 11, 'PO' => 11, 'L'  => 12, 'NGE' => 12, 'GE'  => 13,
    'NL'  => 13, 'LE' => 14, 'NG' => 14, 'G'   => 15, 'NLE' => 15,
  }
end
expand_parameters(command) click to toggle source
# File lib/wilson.rb, line 100
def expand_parameters command
  command.parameters.each_with_index do |parameter, index|
    if String === parameter && parameter =~ /^r\/m(\d+)/ then
      bits = $1.to_i
      newCommand = command.dup
      commands << newCommand
      case bits
      when 8, 16, 32 then
        command.parameters[index]    = MemoryRegister.new bits
        newCommand.parameters[index] = Address.new false, bits
      when 64 then
        command.parameters[index]    = MMXRegister.new bits
        newCommand.parameters[index] = Address.new false, bits
      end
    end
  end
end
parse() click to toggle source
# File lib/wilson.rb, line 174
def parse
  (self.class.nasm + self.class.nasm_fixes).each_line do |line|
    self.process_line line.strip.sub(/^# /, '')
  end

  self
end
parse_command(line) click to toggle source
# File lib/wilson.rb, line 157
def parse_command line
  if line =~ /^(\w+)\s+([^;]*)\s+;\s+([^\[]+)\s+\[([\w,]+)\]/ then
    name, params, ops, procs = $1, $2, $3, $4

    command            = Command.new
    command.opcode     = name
    command.opcodes    = ops.split
    command.processors = procs.split(/,/)

    command.initialize_parameters params.strip

    self.add_command command
  else
    raise "unparsed: #{line}"
  end
end
process_line(line) click to toggle source
# File lib/wilson.rb, line 133
def process_line line # TODO: remove
  return if line.empty?
  return unless line =~ /^[A-Z].+;.*\[/

  self.parse_command line
end