Class: Wilson::Assembler

Inherits:
Object show all
Defined in:
lib/wilson.rb

Overview

Assembler parses the NASM documentation and creates Command objects for it

Constant Summary collapse

@@default =
nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAssembler

Returns a new instance of Assembler.



184
185
186
# File 'lib/wilson.rb', line 184

def initialize
  self.commands = []
end

Instance Attribute Details

#commandsObject

Returns the value of attribute commands.



133
134
135
# File 'lib/wilson.rb', line 133

def commands
  @commands
end

Class Method Details

.commandsObject



176
177
178
# File 'lib/wilson.rb', line 176

def self.commands
  self.default.commands
end

.defaultObject



168
169
170
# File 'lib/wilson.rb', line 168

def self.default
  @@default ||= self.new.parse
end

.default=(o) ⇒ Object



172
173
174
# File 'lib/wilson.rb', line 172

def self.default= o
  @@default = o
end

.nasmObject



162
163
164
# File 'lib/wilson.rb', line 162

def self.nasm
  File.read(__FILE__).split(/__END__/).last
end

.nasm_fixesObject



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/wilson.rb', line 135

def self.nasm_fixes
  # TODO: extend parser to split /[,:]/ and remove some of these
  '
   CALL imm,imm16 ; o16 9A iw iw         [8086]
   CALL imm,imm32 ; o32 9A id iw         [386]
   CALLFAR mem16  ; o16 FF /3            [8086]
   CALLFAR mem32  ; o32 FF /3            [386]

   Jcc imm        ; 0F 80+cc rw/rd       [386]

   JMP imm,imm16  ; o16 EA iw iw         [8086]
   JMP imm,imm32  ; o32 EA id iw         [386]
   JMP imm16      ; E9 rw/rd             [8086]
   JMP imm32      ; E9 rw/rd             [8086]
   JMP imm8       ; EB rb                [8086]
   JMPFAR mem16   ; o16 FF /5            [8086]
   JMPFAR mem32   ; o32 FF /5            [386]

   FADDTO fpureg  ; DC C0+r              [8086,FPU]
   FDIVTO fpureg  ; DC F8+r              [8086,FPU]
   FDIVRTO fpureg ; DC F0+r              [8086,FPU]
   FMULTO fpureg  ; DC C8+r              [8086,FPU]
   FSUBTO fpureg  ; DC E8+r              [8086,FPU]
   FSUBRTO fpureg ; DC E0+r              [8086,FPU]
  '
end

.parseObject



180
181
182
# File 'lib/wilson.rb', line 180

def self.parse
  self.new.parse
end

Instance Method Details

#add_command(command) ⇒ Object



228
229
230
231
232
# File 'lib/wilson.rb', line 228

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) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/wilson.rb', line 206

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

#conditionalsObject



234
235
236
237
238
239
240
241
242
243
# File 'lib/wilson.rb', line 234

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) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/wilson.rb', line 188

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

#parseObject



262
263
264
265
266
267
# File 'lib/wilson.rb', line 262

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) ⇒ Object



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/wilson.rb', line 245

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) ⇒ Object

TODO: remove



221
222
223
224
225
226
# File 'lib/wilson.rb', line 221

def process_line line # TODO: remove
  return if line.empty?
  return unless line =~ /^[A-Z].+;.*\[/

  self.parse_command line
end