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.
263 264 265 |
# File 'lib/wilson.rb', line 263 def opcode @opcode end |
#opcodes ⇒ Object
Returns the value of attribute opcodes.
263 264 265 |
# File 'lib/wilson.rb', line 263 def opcodes @opcodes end |
#parameters ⇒ Object
Returns the value of attribute parameters.
263 264 265 |
# File 'lib/wilson.rb', line 263 def parameters @parameters end |
#processors ⇒ Object
Returns the value of attribute processors.
263 264 265 |
# File 'lib/wilson.rb', line 263 def processors @processors end |
Instance Method Details
#align16_on(instruction, stream) ⇒ Object
471 472 473 |
# File 'lib/wilson.rb', line 471 def align16_on instruction, stream stream << 0x66 if instruction.machine.bits != 16 end |
#align32_on(instruction, stream) ⇒ Object
506 507 508 |
# File 'lib/wilson.rb', line 506 def align32_on instruction, stream stream << 0x67 if instruction.machine.bits != 32 end |
#assemble(instruction) ⇒ Object
379 380 381 382 383 384 385 386 387 388 |
# File 'lib/wilson.rb', line 379 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
265 266 267 268 269 270 |
# File 'lib/wilson.rb', line 265 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
390 391 392 393 394 395 396 397 398 399 400 401 402 403 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 |
# File 'lib/wilson.rb', line 390 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
375 376 377 |
# File 'lib/wilson.rb', line 375 def initialize_parameters params self.parameters = params.split(/,/).map { |s| self.to_parameter s } end |
#instruction_applies?(instruction) ⇒ Boolean
302 303 304 305 306 307 308 309 |
# File 'lib/wilson.rb', line 302 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
510 511 512 513 514 515 516 |
# File 'lib/wilson.rb', line 510 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
502 503 504 |
# File 'lib/wilson.rb', line 502 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“
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 |
# File 'lib/wilson.rb', line 442 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 ==
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 |
# File 'lib/wilson.rb', line 273 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
490 491 492 |
# File 'lib/wilson.rb', line 490 def relative_b_on instruction, stream relative_x_on instruction, stream, :push_B, 2 end |
#relative_d_on(instruction, stream) ⇒ Object
494 495 496 |
# File 'lib/wilson.rb', line 494 def relative_d_on instruction, stream relative_x_on instruction, stream, :push_D, 5 end |
#relative_w_on(instruction, stream) ⇒ Object
498 499 500 |
# File 'lib/wilson.rb', line 498 def relative_w_on instruction, stream relative_x_on instruction, stream, :push_W, 3 end |
#relative_x_on(instruction, stream, msg, dist) ⇒ Object
475 476 477 478 479 480 481 482 483 484 485 486 487 488 |
# File 'lib/wilson.rb', line 475 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
311 312 313 314 315 316 317 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 365 366 367 368 369 370 371 372 373 |
# File 'lib/wilson.rb', line 311 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 |