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.
277 278 279 |
# File 'lib/wilson.rb', line 277 def opcode @opcode end |
#opcodes ⇒ Object
Returns the value of attribute opcodes.
277 278 279 |
# File 'lib/wilson.rb', line 277 def opcodes @opcodes end |
#parameters ⇒ Object
Returns the value of attribute parameters.
277 278 279 |
# File 'lib/wilson.rb', line 277 def parameters @parameters end |
#processors ⇒ Object
Returns the value of attribute processors.
277 278 279 |
# File 'lib/wilson.rb', line 277 def processors @processors end |
Instance Method Details
#align16_on(instruction, stream) ⇒ Object
485 486 487 |
# File 'lib/wilson.rb', line 485 def align16_on instruction, stream stream << 0x66 if instruction.machine.bits != 16 end |
#align32_on(instruction, stream) ⇒ Object
520 521 522 |
# File 'lib/wilson.rb', line 520 def align32_on instruction, stream stream << 0x67 if instruction.machine.bits != 32 end |
#assemble(instruction) ⇒ Object
393 394 395 396 397 398 399 400 401 402 |
# File 'lib/wilson.rb', line 393 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
279 280 281 282 283 284 |
# File 'lib/wilson.rb', line 279 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
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 |
# File 'lib/wilson.rb', line 404 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
389 390 391 |
# File 'lib/wilson.rb', line 389 def initialize_parameters params self.parameters = params.split(/,/).map { |s| self.to_parameter s } end |
#instruction_applies?(instruction) ⇒ Boolean
316 317 318 319 320 321 322 323 |
# File 'lib/wilson.rb', line 316 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
524 525 526 527 528 529 530 |
# File 'lib/wilson.rb', line 524 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
516 517 518 |
# File 'lib/wilson.rb', line 516 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“
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
# File 'lib/wilson.rb', line 456 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 ==
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/wilson.rb', line 287 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
504 505 506 |
# File 'lib/wilson.rb', line 504 def relative_b_on instruction, stream relative_x_on instruction, stream, :push_B, 2 end |
#relative_d_on(instruction, stream) ⇒ Object
508 509 510 |
# File 'lib/wilson.rb', line 508 def relative_d_on instruction, stream relative_x_on instruction, stream, :push_D, 5 end |
#relative_w_on(instruction, stream) ⇒ Object
512 513 514 |
# File 'lib/wilson.rb', line 512 def relative_w_on instruction, stream relative_x_on instruction, stream, :push_W, 3 end |
#relative_x_on(instruction, stream, msg, dist) ⇒ Object
489 490 491 492 493 494 495 496 497 498 499 500 501 502 |
# File 'lib/wilson.rb', line 489 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
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 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 |
# File 'lib/wilson.rb', line 325 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 |