Class: Wilson::Command
Overview
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.
Instance Attribute Summary collapse
-
#opcode ⇒ Object
Returns the value of attribute opcode.
-
#opcodes ⇒ Object
Returns the value of attribute opcodes.
-
#parameters ⇒ Object
Returns the value of attribute parameters.
-
#processors ⇒ Object
Returns the value of attribute processors.
Instance Method Summary collapse
- #align16_on(instruction, stream) ⇒ Object
- #align32_on(instruction, stream) ⇒ Object
- #assemble(instruction) ⇒ Object
- #dup ⇒ Object
- #execute_instruction_position_on(byte, instruction, position, stream) ⇒ Object
- #initialize_parameters(params) ⇒ Object
- #instruction_applies?(instruction) ⇒ Boolean
- #modrm_instruction_on(byte, instruction, stream) ⇒ Object
- #modrm_n_instruction_on(id, instruction, stream) ⇒ Object
-
#modrm_r_on(instruction, stream) ⇒ Object
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“.
-
#parameter_matches(a, b) ⇒ Object
TODO: learn this better, and figure out why not polymorphic ==.
- #relative_b_on(instruction, stream) ⇒ Object
- #relative_d_on(instruction, stream) ⇒ Object
- #relative_w_on(instruction, stream) ⇒ Object
- #relative_x_on(instruction, stream, msg, dist) ⇒ Object
- #to_parameter(parameter) ⇒ Object
Instance Attribute Details
#opcode ⇒ Object
Returns the value of attribute opcode.
191 192 193 |
# File 'lib/wilson.rb', line 191 def opcode @opcode end |
#opcodes ⇒ Object
Returns the value of attribute opcodes.
191 192 193 |
# File 'lib/wilson.rb', line 191 def opcodes @opcodes end |
#parameters ⇒ Object
Returns the value of attribute parameters.
191 192 193 |
# File 'lib/wilson.rb', line 191 def parameters @parameters end |
#processors ⇒ Object
Returns the value of attribute processors.
191 192 193 |
# File 'lib/wilson.rb', line 191 def processors @processors end |
Instance Method Details
#align16_on(instruction, stream) ⇒ Object
399 400 401 |
# File 'lib/wilson.rb', line 399 def align16_on instruction, stream stream << 0x66 if instruction.machine.bits != 16 end |
#align32_on(instruction, stream) ⇒ Object
434 435 436 |
# File 'lib/wilson.rb', line 434 def align32_on instruction, stream stream << 0x67 if instruction.machine.bits != 32 end |
#assemble(instruction) ⇒ Object
307 308 309 310 311 312 313 314 315 316 |
# File 'lib/wilson.rb', line 307 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 ⇒ Object
193 194 195 196 197 198 |
# File 'lib/wilson.rb', line 193 def dup x = super x.parameters = x.parameters.dup x.opcodes = x.opcodes.dup x end |
#execute_instruction_position_on(byte, instruction, position, stream) ⇒ Object
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 |
# File 'lib/wilson.rb', line 318 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) ⇒ Object
303 304 305 |
# File 'lib/wilson.rb', line 303 def initialize_parameters params self.parameters = params.split(/,/).map { |s| self.to_parameter s } end |
#instruction_applies?(instruction) ⇒ Boolean
230 231 232 233 234 235 236 237 |
# File 'lib/wilson.rb', line 230 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) ⇒ Object
438 439 440 441 442 443 444 |
# File 'lib/wilson.rb', line 438 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) ⇒ Object
430 431 432 |
# File 'lib/wilson.rb', line 430 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) ⇒ Object
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“
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
# File 'lib/wilson.rb', line 370 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) ⇒ Object
TODO: learn this better, and figure out why not polymorphic ==
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/wilson.rb', line 201 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) ⇒ Object
418 419 420 |
# File 'lib/wilson.rb', line 418 def relative_b_on instruction, stream relative_x_on instruction, stream, :push_B, 2 end |
#relative_d_on(instruction, stream) ⇒ Object
422 423 424 |
# File 'lib/wilson.rb', line 422 def relative_d_on instruction, stream relative_x_on instruction, stream, :push_D, 5 end |
#relative_w_on(instruction, stream) ⇒ Object
426 427 428 |
# File 'lib/wilson.rb', line 426 def relative_w_on instruction, stream relative_x_on instruction, stream, :push_W, 3 end |
#relative_x_on(instruction, stream, msg, dist) ⇒ Object
403 404 405 406 407 408 409 410 411 412 413 414 415 416 |
# File 'lib/wilson.rb', line 403 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) ⇒ Object
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/wilson.rb', line 239 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 |