class Command
Command is a potential command you can call. It has an opcode (eg: MOV) and the memory format that it outputs as (opcodes) as well as the kinds of parameters it takes and the processor types that support the command.
Attributes
opcode[RW]
opcodes[RW]
parameters[RW]
processors[RW]
Public Instance Methods
align16_on(instruction, stream)
click to toggle source
# File lib/wilson.rb, line 398 def align16_on instruction, stream stream << 0x66 if instruction.machine.bits != 16 end
align32_on(instruction, stream)
click to toggle source
# File lib/wilson.rb, line 433 def align32_on instruction, stream stream << 0x67 if instruction.machine.bits != 32 end
assemble(instruction)
click to toggle source
# File lib/wilson.rb, line 306 def assemble instruction stream = [] opcodes.each_with_index do |each, index| self.execute_instruction_position_on(each, instruction, (index + 1) / opcodes.size, stream) end stream end
dup()
click to toggle source
Calls superclass method
# File lib/wilson.rb, line 192 def dup x = super x.parameters = x.parameters.dup x.opcodes = x.opcodes.dup x end
execute_instruction_position_on(byte, instruction, position, stream)
click to toggle source
# File lib/wilson.rb, line 317 def execute_instruction_position_on(byte, instruction, position, stream) case byte when 'a16', 'a32' then raise "not done yet" when 'o16' then return self.align16_on(instruction, stream) when 'o32' then return self.align32_on(instruction, stream) when 'ib' then return stream.push_B(instruction.theImmediate) when 'iw' then return stream.push_W(instruction.theSecondImmediate) if position == 1 return stream.push_W(instruction.theImmediate) when 'id' then return stream.push_D(instruction.theSecondImmediate) if position == 1 return stream.push_D(instruction.theImmediate) when 'rb' then return self.relative_b_on(instruction, stream) when 'rw' then return self.relative_w_on(instruction, stream) when 'rw/rd' then return self.relative_w_on(instruction, stream) if instruction.machine.bits == 16 return self.relative_d_on(instruction, stream) when 'rd' then return self.relative_d_on(instruction, stream) when 'ow' then raise byte # [^stream push_W: instruction theAddress offset]. when 'od' then raise byte # [^stream push_D: instruction theAddress offset]. when 'ow/od' then if instruction.machine.bits == 16 then stream.push_W instruction.theAddress.offset end return stream.push_D(instruction.theAddress.offset) when /^\/(.*)/ then return self.modrm_instruction_on($1, instruction, stream) end number = byte.hex number += instruction.parameters[parameters.first.id ? 1 : 0].id if byte =~ /r$/ stream << number end
initialize_parameters(params)
click to toggle source
# File lib/wilson.rb, line 302 def initialize_parameters params self.parameters = params.split(/,/).map { |s| self.to_parameter s } end
instruction_applies?(instruction)
click to toggle source
# File lib/wilson.rb, line 229 def instruction_applies? instruction return false if instruction.opcode != self.opcode return false if instruction.parameters.size != self.parameters.size instruction.parameters.zip(self.parameters).all? { |a, b| self.parameter_matches a, b } end
modrm_instruction_on(byte, instruction, stream)
click to toggle source
# File lib/wilson.rb, line 437 def modrm_instruction_on byte, instruction, stream if byte == "r" then self.modrm_r_on instruction, stream else self.modrm_n_instruction_on byte.to_i, instruction, stream end end
modrm_n_instruction_on(id, instruction, stream)
click to toggle source
# File lib/wilson.rb, line 429 def modrm_n_instruction_on id, instruction, stream instruction.first.push_mod_rm_on Register.on_id_bits(instruction.machine, id, instruction.first.bits), stream end
modrm_r_on(instruction, stream)
click to toggle source
If we get here, there will be at least two parameters to combine a memory address with a register or a register with a register“
# File lib/wilson.rb, line 369 def modrm_r_on instruction, stream address, register = instruction.first, instruction.second swap = false # TODO: this can be 1 call at the bottom if instruction.first.register? && instruction.second.register? then if parameters.first.memory_register? then return instruction.first.push_mod_rm_on(instruction.second, stream) else return instruction.second.push_mod_rm_on(instruction.first, stream) end end if instruction.first.special_register? then return instruction.second.push_mod_rm_on(instruction.first, stream) end if instruction.second.special_register? then return instruction.first.push_mod_rm_on(instruction.second, stream) end address, register = if instruction.first.register? && instruction.second.respond_to?(:push_mod_rm_on) then [instruction.second, instruction.first] else [instruction.first, instruction.second] end address.push_mod_rm_on register, stream end
parameter_matches(a, b)
click to toggle source
TODO: learn this better, and figure out why not polymorphic ==
# File lib/wilson.rb, line 200 def parameter_matches a, b return false if String === b if a.register? && b.register? then return a.bits == b.bits && (b.id.nil? || a.id == b.id) end if a.address? && b.address? then return ! b.offset? || a.offset? end if a.special_register? && b.special_register? then return a.class == b.class && (b.id.nil? || a.id == b.id) end return false unless b.immediate? if a.immediate_value? then return (b.value && b.value == a) || b.bits.nil? || a < (2 ** b.bits) end if a.label? then return a.future_label? ? b.bits == a.machine.bits : a.bits <= (b.bits || a.machine.bits) end false end
relative_b_on(instruction, stream)
click to toggle source
# File lib/wilson.rb, line 417 def relative_b_on instruction, stream relative_x_on instruction, stream, :push_B, 2 end
relative_d_on(instruction, stream)
click to toggle source
# File lib/wilson.rb, line 421 def relative_d_on instruction, stream relative_x_on instruction, stream, :push_D, 5 end
relative_w_on(instruction, stream)
click to toggle source
# File lib/wilson.rb, line 425 def relative_w_on instruction, stream relative_x_on instruction, stream, :push_W, 3 end
relative_x_on(instruction, stream, msg, dist)
click to toggle source
# File lib/wilson.rb, line 402 def relative_x_on instruction, stream, msg, dist offset = instruction.first offset = offset.offset if offset.offset? if offset.label? then if offset.future_label? then offset.add instruction.machine.stream.size return stream.send(msg, dist) end offset = offset.position end stream.send(msg, -(instruction.machine.stream.size - offset + dist)) end
to_parameter(parameter)
click to toggle source
# File lib/wilson.rb, line 238 def to_parameter parameter case parameter when 'r/m8' then return parameter # "Expanded by the parser" when 'r/m16' then return parameter # "Expanded by the parser" when 'r/m32' then return parameter # "Expanded by the parser" when 'r/m64' then return parameter # "Expanded by the parser" when 'TO fpureg' then return parameter # "Fixed in nasm_fixes" when 'SHORT imm' then return parameter # "Fixed in nasm_fixes" when 'FAR mem' then return parameter # "Fixed in nasm_fixes" when 'FAR mem16' then return parameter # "Fixed in nasm_fixes" when 'FAR mem32' then return parameter # "Fixed in nasm_fixes" when 'NEAR imm' then return parameter # "Fixed in nasm_fixes" when 'imm:imm16' then return parameter # "Fixed in nasm_fixes" when 'imm:imm32' then return parameter # "Fixed in nasm_fixes" when '1' then return Immediate.new(1) when 'AL' then return Register.on_id_bits(nil, 0, 8) when 'AX' then return Register.on_id_bits(nil, 0, 16) when 'EAX' then return Register.on_id_bits(nil, 0, 32) when 'CL' then return Register.on_id_bits(nil, 1, 8) when 'CX' then return Register.on_id_bits(nil, 1, 16) when 'ECX' then return Register.on_id_bits(nil, 1, 32) when 'DL' then return Register.on_id_bits(nil, 2, 8) when 'DX' then return Register.on_id_bits(nil, 2, 16) when 'EDX' then return Register.on_id_bits(nil, 2, 32) when 'BL' then return Register.on_id_bits(nil, 3, 8) when 'BX' then return Register.on_id_bits(nil, 3, 16) when 'EBX' then return Register.on_id_bits(nil, 3, 32) when 'ES' then return SegmentRegister.on_id(nil, 0) when 'CS' then return SegmentRegister.on_id(nil, 1) when 'SS' then return SegmentRegister.on_id(nil, 2) when 'DS' then return SegmentRegister.on_id(nil, 3) when 'FS' then return SegmentRegister.on_id(nil, 4) when 'GS' then return SegmentRegister.on_id(nil, 5) when 'imm' then return Immediate.new when 'imm8' then return Immediate.new(8) when 'imm16' then return Immediate.new(16) when 'imm32' then return Immediate.new(32) when 'segreg' then return SegmentRegister.new when 'reg' then return Register.new when 'reg8' then return Register.new(8) when 'reg16' then return Register.new(16) when 'reg32' then return Register.new(32) when 'mem' then return Address.new(false, 4) when 'mem8' then return Address.new(false, 8) when 'mem16' then return Address.new(false, 16) when 'mem32' then return Address.new(false, 32) when 'mem64' then return Address.new(false, 64) when 'mem80' then return Address.new(false, 80) when 'memoffs8' then return Address.new(true, 8) when 'memoffs16' then return Address.new(true, 16) when 'memoffs32' then return Address.new(true, 32) when 'fpureg' then return FPURegister.new when /ST(.*)/ then return FPURegister.new($1.to_i) when 'mmxreg' then return MMXRegister.new when /MM(.*)/ then return MMXRegister.new($1.to_i) when 'CR0/2/3/4' then return ControlRegister.new when 'DR0/1/2/3/6/7' then return DebugRegister.new when 'TR3/4/5/6/7' then return TestRegister.new else warn "unknown parameter: #{parameter.inspect}" return parameter end end