CSES - Datatähti 2018 alku - Results
Submission details
Task:Fraktaali
Sender:ollpu
Submission time:2018-09-26 20:39:27 +0300
Language:Ruby
Status:READY
Result:100
Feedback
groupverdictscore
#1ACCEPTED10
#2ACCEPTED10
#3ACCEPTED10
#4ACCEPTED10
#5ACCEPTED10
#6ACCEPTED10
#7ACCEPTED10
#8ACCEPTED10
#9ACCEPTED10
#10ACCEPTED10
Test results
testverdicttimegroup
#1ACCEPTED0.11 s1details
#2ACCEPTED0.12 s2details
#3ACCEPTED0.12 s3details
#4ACCEPTED0.11 s4details
#5ACCEPTED0.12 s5details
#6ACCEPTED0.12 s6details
#7ACCEPTED0.11 s7details
#8ACCEPTED0.11 s8details
#9ACCEPTED0.11 s9details
#10ACCEPTED0.12 s10details

Code

def main
  n = gets.to_i-1
  bs = (1<<2*n) + (1<<n)
  mem = Fiddle.malloc bs
  asm do
    rbp.mov mem
    rcx.xor rcx
    
    rdi.xor rdi
    l1 = label
    rsi.xor rsi
    l2 = label
    
    rax.mov rdi
    rax.and rsi
    rax.popcnt rax
    al.test 1
    jz even = flabel
    
    eax.mov ".".ord
    jmp over = flabel
    
    even.plant
    eax.mov "#".ord
    
    over.plant
    mov rbp+rcx, al
    rcx.inc
    rsi.inc
    rdx.mov 1<<n
    rsi.cmp rdx
    jl l2
    eax.mov "\n".ord
    mov rbp+rcx, al
    rcx.inc
    rdi.inc
    rdx.mov 1<<n
    rdi.cmp rdx
    jl l1
    
    rax.mov 1
    rdi.mov 1
    rsi.mov mem
    rdx.mov rcx
    syscall
  end
end

##
# Wilson is a pure ruby x86 assembler. No, really. Worst Idea Evar.
# Source: https://github.com/seattlerb/wilson/
# Modded by ollpu to run in modern Ruby (Linux x86_64)
##
#
# Why "wilson"? I wanted to name it "metal", but there is an existing
# project with that name... So I'm naming it after Wilson Bilkovich, who
# is about as metal as you can get (and it is easier to spell than
# "bilkovich", even tho that sounds more metal).
#
# Wilson is a port (and extension) of the smalltalk x86 assembler by
# Michael Lucas-Smith. I came across it when he presented it at
# Smalltalk SuperPowers at OOPSLA 2008.

require 'fiddle'
require 'fiddle/import'

module LibC
  extend Fiddle::Importer
  dlload "libc.so.6"
  extern "void* mmap(void*, size_t, int, int, int, ptrdiff_t)"
  extern "void* memcpy(void*, const void*, size_t)"
  def self.mmap_rwx length
    LibC.mmap(0, length, 0x7, 0x22, -1, 0)
  end
end

class Object
  def subclass_responsibility; raise "subclass responsibility" end
  def no!; false end

  alias :address?          :no!
  alias :future_label?     :no!
  alias :immediate?        :no!
  alias :immediate_value?  :no!
  alias :label?            :no!
  alias :offset?           :no!
  alias :operand?          :no!
  alias :register?         :no!
  alias :special_register? :no!
end


module Wilson
  VERSION = '1.1.2'

  ##
  # Assembler parses the NASM documentation and creates Command
  # objects for it

  class Assembler
    attr_accessor :commands
    attr_accessor :commands_by_mnemonic

    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 imm16        ; 0F 80+cc rw/rd       [386]
       Jcc imm32        ; 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]

       CMP r/m16,imm8 ; o16 83 /7 ib         [8086]
       CMP r/m32,imm8 ; o32 83 /7 ib         [386]
       SAR r/m16,1    ; o16 D1 /7            [8086]
       SAR r/m32,1    ; o32 D1 /7            [386]
       
       MOV reg64,imm64 ; o32 B8+r id [x64]
       
       SYSCALL        ; 0F 05                [x64]
       POPCNT reg16,r/m16 ; f3 o16 0f b8 /r     [NEHALEM]
       POPCNT reg32,r/m32 ; f3 o32 0f b8 /r     [NEHALEM]
      '
    end

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

    @@default = nil

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

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

    def self.commands
      self.default.commands
    end
    
    def self.commands_by_mnemonic
      self.default.commands_by_mnemonic
    end

    def self.parse
      self.default
    end

    def initialize
      self.commands = []
      self.commands_by_mnemonic = {}
    end

    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

    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

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

      self.parse_command line
    end

    def add_command command
      return self.add_conditional_commands(command) if command.opcode =~ /cc$/i
      self.commands << command
      self.expand_parameters command
    end

    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

    def parse_command line
      if line =~ /^(\w+)\s+([^;]*)\s*;\s*([^\[]+)\s+/ then
        name, params, ops = $1, $2, $3

        command            = Command.new
        command.opcode     = name
        command.opcodes    = ops.split

        command.initialize_parameters params.strip

        self.add_command command
      else
        raise "unparsed: #{line}"
      end
    end

    def parse
      (self.class.nasm + self.class.nasm_fixes).each_line do |line|
        self.process_line line.strip
      end
      self.commands.each do |cmd|
        self.commands_by_mnemonic[cmd.opcode] ||= []
        self.commands_by_mnemonic[cmd.opcode] << cmd
      end
      self
    end
  end

  ##
  # 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.

  class Command
    attr_accessor :opcode, :parameters, :opcodes

    def dup
      x            = super
      x.parameters = x.parameters.dup
      x.opcodes    = x.opcodes.dup
      x
    end

    # TODO: learn this better, and figure out why not polymorphic ==
    def parameter_matches a, b
      return false if String === b

      if a.register? && b.register? then
        return (a.bits == b.bits || [a.bits, b.bits] == [64, 32] ) && (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

    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

    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 'imm64'         then return Immediate.new(64)
      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 'reg64'         then return Register.new(64)
      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
    
    def initialize_parameters params
      self.parameters = params.split(/,/).map { |s| self.to_parameter s }
    end

    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

    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
        if instruction.x64_mode
          return stream.push_Q(instruction.theSecondImmediate) if position == 1
          return stream.push_Q(instruction.theImmediate)
        else
          return stream.push_D(instruction.theSecondImmediate) if position == 1
          return stream.push_D(instruction.theImmediate)
        end
      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

    ##
    # 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"

    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

    def align16_on instruction, stream
      stream << 0x66 if instruction.machine.bits != 16
    end

    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 + stream.size
          return stream.send(msg, dist)
        end
        offset = offset.position
      end

      stream.send(msg, -(instruction.machine.stream.size - offset + dist))
    end

    def relative_b_on instruction, stream
      relative_x_on instruction, stream, :push_B, 1
    end

    def relative_w_on instruction, stream
      relative_x_on instruction, stream, :push_W, 2
    end
    
    def relative_d_on instruction, stream
      relative_x_on instruction, stream, :push_D, 4
    end

    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

    def align32_on instruction, stream
      if instruction.parameters.any? { |par| par.register? && par.bits == 32 }
        stream << 0x67 if instruction.machine.bits != 32
      else
        stream << 0x48
        instruction.x64_mode = true
      end
    end

    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
  end

  ##
  # Instruction is an instruction shape that we're going to match to
  # Commands to find out what we should write in to memory.

  class Instruction
    attr_accessor :opcode, :machine, :parameters, :x64_mode

    def self.on_message machine, message # TODO: remove
      self.new message, machine
    end

    def initialize message, machine
      self.machine = machine
      self.opcode, *self.parameters = message
      self.opcode = opcode.to_s.upcase

      self.machine = parameters[1].machine unless machine

      self.parameters.map! { |each| Proc === each ? each.call.m : each }

      self.parameters.each do |each|
        each.machine = self.machine if each.operand?
      end
      self.x64_mode = false
    end

    def first
      parameters.first
    end

    def second
      parameters.second
    end

    def theAddress
      parameters.detect { |e| e.address? }
    end

    def assemble
      instructions = machine.instructions_by_mnemonic[self.opcode].select { |command|
        command.instruction_applies? self
      }

      return false if instructions.empty?
      
      # Heuristically select "smallest" instruction
      instruction = instructions.each.with_index.min_by { |inst, i| [inst.opcodes.size, i] }.first

      machine.stream.concat(instruction.assemble self)
      true
    end

    def theSecondImmediate
      parameters.detect { |e| e.immediate_value? }
    end

    def theImmediate
      parameters.reverse.detect { |e| e.immediate_value? }
    end
  end

  ##
  # MachineCode is an abstract machine that has subclasses for each
  # concrete machine type that you can write assembly language for.
  # Right now this library only supports X86, so look at
  # MachineCodeX86 for more details on how to use it.

  class MachineCode
    attr_accessor :stream, :procedure, :bits
    attr_accessor :instructions_by_mnemonic

    def initialize
      self.procedure  = nil
      self.bits       = self.defaultBits
      self.stream     = []

      self.setupMachine
    end

    def inspect
      "#{self.class}#{stream.inspect}"
    end

    def method_missing msg, *args
      super unless self.instructionFromMessage(msg, *args).assemble
    end

    def instructionFromMessage msg, *args
      Instruction.on_message self, [msg, *args]
    end

    def label
      Label.on_at(self, stream.size)
    end

    def flabel
      FutureLabel.on self
    end

    def assemble instruction
      raise "no"
      #     aBlock on: MessageNotUnderstood do: [:ex |
      #         ex originator class = BlockClosure ifFalse: [ex pass].
      #         ex resume: (ex originator value m perform: ex parameter selector withArguments: ex parameter arguments)]</body>
    end

    alias :setupMachine :subclass_responsibility
    alias :platform     :subclass_responsibility
    alias :defaultBits  :subclass_responsibility
  end

  ##
  # MachineCodeX86 is a concrete implementation of a machine to create
  # X86 assembly code on.
  #
  # You can use this class in two ways:
  #
  # a) you can instantiate an instance and use its register variables
  #    to build up machine code in the @stream variable and then use
  #    those bytes in any way that you see fit, or
  #
  # b) you can make a subclass of this class much like you do with
  #    ExternalInterface and put methods on the class that will
  #    compile in to assembler code that can be called from Smalltalk
  #    code
  #
  # == Using MachineCodeX86 for scripting
  #
  # This is the long hand way of writing assembly code, since you
  # always include a receiver with every command.
  #
  #     asm = Assembler.MachineCodeX86.new
  #
  # Once you have an assembler, you can access the registers and send
  # commands to them, eg:
  #
  #     asm.eax.mov 1
  #
  # As you send the commands, the @stream will build up containing the
  # X86 assembler bytes you can use. You can use memory addresses in
  # your assembler code with the #m method, eg:
  #
  #     asm.eax.m.mov 1
  #
  # Once you are finished, you simply send:
  #
  #     asm.stream
  #
  # This will return you the stream of bytes.
  #
  # == Labels & Jumps
  #
  # You can do labels and jump to them using two different label
  # commands. The first is #label, which places a label jump point
  # immediately on call, eg:
  #
  #         label = asm.label
  #         label.jmp
  #
  # The other is a future label that can be placed at some future
  # point in the program and jumped too
  #
  #         label = asm.future_label
  #         asm.eax.xor asm.eax
  #         label.jmp
  #         asm.eax.inc
  #         label.plant
  #
  # You #plant the future label where you want it to actually be and
  # past references to it will be updated. Future labels will always
  # use a dword jmp so that there's space to fill in the command if
  # the jmp ends up being far.

  class MachineCodeX86 < MachineCode
    # registers-general-64bit
    attr_accessor :rax, :rbx, :rbp, :rsp, :rdi, :rsi, :rcx, :rdx
    
    # Not supported yet
    # attr_accessor :r8, :r9, :r10, :r11, :r12, :r13, :r14, :r15
    
    # registers-general-32bit
    attr_accessor :eax, :ebx, :ebp, :esp, :edi, :esi, :ecx, :edx

    # registers-fpu
    attr_accessor :st0, :st1, :st2, :st3, :st4, :st5, :st6, :st7

    # registers-debug
    attr_accessor :dr0, :dr1, :dr2, :dr3, :dr6, :dr7

    # registers-segment
    attr_accessor :es, :ss, :cs, :gs, :fs, :ds

    # registers-test
    attr_accessor :tr3, :tr4, :tr5, :tr6, :tr7

    # registers-general-8bit
    attr_accessor :al, :ah, :bl, :bh, :cl, :ch, :dl, :dh

    # registers-general-16bit
    attr_accessor :ax, :bx, :cx, :dx, :sp, :bp, :si, :di

    # registers-control
    attr_accessor :cr0, :cr2, :cr3, :cr4

    # registers-mmx
    attr_accessor :mm0, :mm1, :mm2, :mm3, :mm4, :mm5, :mm6, :mm7

    def setupMachine
      self.instructions_by_mnemonic = Assembler.commands_by_mnemonic

      self.setup8BitRegisters
      self.setup16BitRegisters
      self.setup32BitRegisters
      self.setup64BitRegisters
      self.setupSegmentRegisters
      self.setupControlRegisters
      self.setupTestRegisters
      self.setupDebugRegisters
      self.setupFPURegisters
      self.setupMMXRegisters
    end
    
    def setup8BitRegisters
      self.al = Register.on_id_bits self, 0, 8
      self.cl = Register.on_id_bits self, 1, 8
      self.dl = Register.on_id_bits self, 2, 8
      self.bl = Register.on_id_bits self, 3, 8
      self.ah = Register.on_id_bits self, 4, 8
      self.ch = Register.on_id_bits self, 5, 8
      self.dh = Register.on_id_bits self, 6, 8
      self.bh = Register.on_id_bits self, 7, 8
    end

    def setup16BitRegisters
      self.ax = Register.on_id_bits self, 0, 16
      self.cx = Register.on_id_bits self, 1, 16
      self.dx = Register.on_id_bits self, 2, 16
      self.bx = Register.on_id_bits self, 3, 16
      self.sp = Register.on_id_bits self, 4, 16
      self.bp = Register.on_id_bits self, 5, 16
      self.si = Register.on_id_bits self, 6, 16
      self.di = Register.on_id_bits self, 7, 16
    end

    def setupMMXRegisters
      self.mm0 = MMXRegister.on_id self, 0
      self.mm1 = MMXRegister.on_id self, 1
      self.mm2 = MMXRegister.on_id self, 2
      self.mm3 = MMXRegister.on_id self, 3
      self.mm4 = MMXRegister.on_id self, 4
      self.mm5 = MMXRegister.on_id self, 5
      self.mm6 = MMXRegister.on_id self, 6
      self.mm7 = MMXRegister.on_id self, 7
    end

    def setupTestRegisters
      self.tr3 = TestRegister.on_id self, 3
      self.tr4 = TestRegister.on_id self, 4
      self.tr5 = TestRegister.on_id self, 5
      self.tr6 = TestRegister.on_id self, 6
      self.tr7 = TestRegister.on_id self, 7
    end

    def setup32BitRegisters
      self.eax = Register.on_id_bits self, 0, 32
      self.ecx = Register.on_id_bits self, 1, 32
      self.edx = Register.on_id_bits self, 2, 32
      self.ebx = Register.on_id_bits self, 3, 32
      self.esp = Register.on_id_bits self, 4, 32
      self.ebp = Register.on_id_bits self, 5, 32
      self.esi = Register.on_id_bits self, 6, 32
      self.edi = Register.on_id_bits self, 7, 32
    end
    
    def setup64BitRegisters
      self.rax = Register.on_id_bits self, 0, 64
      self.rcx = Register.on_id_bits self, 1, 64
      self.rdx = Register.on_id_bits self, 2, 64
      self.rbx = Register.on_id_bits self, 3, 64
      self.rsp = Register.on_id_bits self, 4, 64
      self.rbp = Register.on_id_bits self, 5, 64
      self.rsi = Register.on_id_bits self, 6, 64
      self.rdi = Register.on_id_bits self, 7, 64
    end
    
    def setupFPURegisters
      self.st0 = FPURegister.on_id self, 0
      self.st1 = FPURegister.on_id self, 1
      self.st2 = FPURegister.on_id self, 2
      self.st3 = FPURegister.on_id self, 3
      self.st4 = FPURegister.on_id self, 4
      self.st5 = FPURegister.on_id self, 5
      self.st6 = FPURegister.on_id self, 6
      self.st7 = FPURegister.on_id self, 7
    end

    def setupControlRegisters
      self.cr0 = ControlRegister.on_id self, 0
      self.cr2 = ControlRegister.on_id self, 2
      self.cr3 = ControlRegister.on_id self, 3
      self.cr4 = ControlRegister.on_id self, 4
    end

    def platform
      'x86_64'
    end

    def setupDebugRegisters
      self.dr0 = DebugRegister.on_id self, 0
      self.dr1 = DebugRegister.on_id self, 1
      self.dr2 = DebugRegister.on_id self, 2
      self.dr3 = DebugRegister.on_id self, 3
      self.dr6 = DebugRegister.on_id self, 6
      self.dr7 = DebugRegister.on_id self, 7
    end

    def defaultBits
      32
    end

    def setupSegmentRegisters
      self.es = SegmentRegister.on_id self, 0
      self.cs = SegmentRegister.on_id self, 1
      self.ss = SegmentRegister.on_id self, 2
      self.ds = SegmentRegister.on_id self, 3
      self.fs = SegmentRegister.on_id self, 4
      self.gs = SegmentRegister.on_id self, 5
    end

    def syscall
      # Override Ruby's syscall
      method_missing :syscall
    end
  end

  ##
  # Operand is any kind of operand used in a command or instruction,
  # eg: registers, memory addresses, labels, immediates, etc.

  class Operand
    attr_accessor :machine, :bits

    def self.on machine
      x = self.new
      x.machine = machine
      x
    end

    # TODO: fix _all_ initialize methods from here down to have cleaner args
    def initialize bits = nil, machine = nil
      @bits = bits
      @machine = machine
    end

    def method_missing msg, *args, &b
      super unless self.instructionFromMessage(msg, *args, &b).assemble
    end

    def instructionFromMessage msg, *args, &b
      Instruction.on_message machine, [msg, self, *args] + (b ? [b] : [])
    end

    def operand?
      true
    end
  end

  ##
  # Immediate is an Integer wrapper so that we know the machine we're
  # dealing with when we apply commands

  class Immediate < Operand
    attr_accessor :value

    def immediate?
      true
    end
  end

  ##
  # Address is a memory address in one of the following example forms:
  #
  #     eax, ebx + ecx, eax + 5, 23545, edx + eax + 2312

  class Address < Operand
    attr_accessor :id, :index
    attr_reader :offset
    attr_writer :isAssemblerOffset # FIX

    def self.on_id_offset machine, id, offset
      address         = self.new
      address.machine = machine
      address.id      = id
      address.offset  = offset
      address
    end

    def initialize isAssemblerOffset = nil, bits = nil, id = nil
      super(bits)

      self.isAssemblerOffset = isAssemblerOffset
      self.id = id

      self.index = self.offset = nil
    end

    def bits
      super || self.machine.bits
    end

    def offset= obj
      if obj.register? then
        @offset = 0
        self.index = obj
      else
        @offset = obj
      end
    end

    def + o # TODO: this seems totally and completely wrong
      if o.register? then
        self.index = o
      else
        self.offset = o
      end
      self
    end

    def address?
      true
    end

    def offset?
      @isAssemblerOffset.nil? ? id.nil? : @isAssemblerOffset
    end

    def push_mod_rm_on spareRegister, stream
      if id.nil? then
        stream << (0b00000101 + (spareRegister.id << 3))
        return stream.push_D(offset)
      end

      # TODO: scale support
      mod = case offset
            when 0 then
              0b00
            when -128..127 then
              0b01
            when -(1<<15)..(1<<15)-1
              0b10
            else
              0b11
            end
      modrm = (mod << 6) | id
      sib = nil
      if index.nil? then
        modrm += (spareRegister.id << 3)
      else
        # use SIB
        modrm = mod << 6 | spareRegister.id << 3 | 0b100
        sib = index.id << 3 | id
        if id == 0b101 and mod == 0b00 # -bp special case
          mod = 0b01
          modrm |= mod << 6
        end
      end
      
      stream << modrm
      stream << sib if sib

      case mod
      when 0b00
        return self
      when 0b01
        return stream.push_B(offset)
      when 0b10
        return stream.push_W(offset)
      when 0b11
        return stream.push_D(offset)
      end
    end

    def m
      self
    end
  end

  ##
  # Register is a general X86 register, such as eax, ebx, ecx, edx,
  # etc...

  class Register < Operand
    attr_accessor :id

    def self.on_id_bits machine, id, bits
      self.new bits, machine, id
    end

    def initialize bits = nil, machine = nil, id = nil
      super(bits, machine)
      self.id = id
    end

    def memory_register?
      false
    end

    def register?
      true
    end

    def get address # TODO: test
      self.mov address
      self.mov {self}
    end

    def push_mod_rm_on spareRegister, stream
      stream << (0b11000000 + id + (spareRegister.id << 3))
    end

    def m
      self + 0
    end

    def - offset
      self + -offset
    end

    def + offset
      Address.on_id_offset machine, id, offset
    end
  end

  ##
  # MemoryRegister is a regular Register, but the parser needs to know
  # if it is a primary or secondary register. This form is a private
  # secondary register. Use Register instead of this guy.

  class MemoryRegister < Register
    def memory_register?
      true
    end
  end

  ##
  # Label is a known point in the byte stream that we can jmp/loop back to.

  class Label < Operand
    attr_accessor :position

    def self.on_at machine, position
      label = self.new
      label.machine = machine
      label.position = position
      label
    end

    def bits
      distance = machine.stream.size - position

      if distance < (1<<7)
        8
      elsif distance < (1<<15)
        16
      elsif distance < (1<<31)
        32
      else
        64
      end
    end

    def label?
      true
    end
  end

  ##
  # FutureLabel is a label in memory that hasn't been defined yet and
  # will go back and fill in the appropriate memory bytes later

  class FutureLabel < Label
    attr_accessor :positions

    def initialize
      super
      self.positions = []
    end

    def plant
      self.position = machine.stream.size

      positions.each do |pos|
        size = machine.stream[pos]
        address = []
        case size
        when 1 then
          address.push_B(position - pos - 1)
        when 2 then
          address.push_W(position - pos - 2)
        when 4 then
          address.push_D(position - pos - 4)
        else
          raise "unhandled size #{size}"
        end

        machine.stream[pos...pos+size] = address
      end
    end

    def future_label?
      position.nil?
    end

    def add aPosition
      positions << aPosition
    end
  end

  ##
  # SpecialRegister is the abstract implementation of any kind of
  # register that isn't a general register, eg: segment registers, mmx
  # registers, fpu registers, etc...

  class SpecialRegister < Operand
    attr_accessor :id

    def self.on_id machine, id
      register = self.new
      register.machine = machine
      register.id = id
      register
    end

    def special_register?
      true
    end
  end

  ##
  # DebugRegister is an X86 DRx register

  class DebugRegister < SpecialRegister
  end

  ##
  # TestRegister is an X86 Test Register, TRx

  class TestRegister < SpecialRegister
  end

  ##
  # FPURegister is an X86 fpureg, STx

  class FPURegister < SpecialRegister
    def initialize id = nil
      super()
      self.id = id
    end
  end

  ##
  # ControlRegister is an X86 CRx register

  class ControlRegister < SpecialRegister
  end

  ##
  # MMXRegister is an X86 MMX register

  class MMXRegister < SpecialRegister
    def push_mod_rm_on spareRegister, stream
      stream << (0b11000000 + id + (spareRegister.id << 3))
    end
  end

  ##
  # SegmentRegister is an X86 segment register, eg: ss, cs, ds, es...

  class SegmentRegister < SpecialRegister
  end
end # module Wilson

require 'rbconfig'

class Integer
  def m
    address = Wilson::Address.new
    address.offset = self
    address
  end

  def immediate_value?
    true
  end

  def inspect
    "0x#{to_s 16}"
  end if $DEBUG
end

class Array
  def second
    self[1]
  end

  def push_B integer
    self << (integer & 255)
  end
  
  def push_W integer
    self.push((integer & 255), (integer >> 8 & 255))
  end
  
  def push_D integer
    self.push(*[integer].pack("V").unpack("C4"))
  end

  def push_Q integer
    self.push_D(integer & (1<<32)-1)
    self.push_D(integer >> 32)
  end
end

class Module
  def defasm name, *args, &block
    fn = assemble(*args, &block)
    define_method(name, &fn)
  end
end

class Object
  def assemble *args, &block
    asm = Wilson::MachineCodeX86.new

    # TODO: enter?
    asm.rbp.push
    asm.rbp.mov asm.rsp

    size = asm.stream.size

    asm.instance_eval(&block)

    if asm.stream.size == size  # return nil
      warn "returning nil for #{self}"
      asm.rax.mov 0
    end

    asm.rbp.pop
    asm.ret

    code = asm.stream.pack("C*")

    if $DEBUG then
      path = "#{$$}.obj"
      File.open path, "wb" do |f|
        f.write code
      end

      puts code.unpack("C*").map { |n| "%02X" % n }.join(' ')
      system "ndisasm -b 64 #{path}"

      File.unlink path
    end

    ptr = LibC.mmap_rwx code.size
    LibC.memcpy(ptr, code, code.size)
    Fiddle::Function.new(ptr, [Fiddle::TYPE_LONG]*args.size, Fiddle::TYPE_LONG)
  end
  
  def asm(*args, &block)
    assemble(*args, &block).call(*args)
  end
  
end

main

__END__
AAA ; 37 [8086]
AAS ; 3F [8086]
AAD ; D5 0A [8086]
AAD imm ; D5 ib [8086]
AAM ; D4 0A [8086]
AAM imm ; D4 ib [8086]
ADC r/m8,reg8 ; 10 /r [8086]
ADC r/m16,reg16 ; o16 11 /r [8086]
ADC r/m32,reg32 ; o32 11 /r [386]
ADC reg8,r/m8 ; 12 /r [8086]
ADC reg16,r/m16 ; o16 13 /r [8086]
ADC reg32,r/m32 ; o32 13 /r [386]
ADC r/m8,imm8 ; 80 /2 ib [8086]
ADC r/m16,imm16 ; o16 81 /2 iw [8086]
ADC r/m32,imm32 ; o32 81 /2 id [386]
ADC r/m16,imm8 ; o16 83 /2 ib [8086]
ADC r/m32,imm8 ; o32 83 /2 ib [386]
ADC AL,imm8 ; 14 ib [8086]
ADC AX,imm16 ; o16 15 iw [8086]
ADC EAX,imm32 ; o32 15 id [386]
ADD r/m8,reg8 ; 00 /r [8086]
ADD r/m16,reg16 ; o16 01 /r [8086]
ADD r/m32,reg32 ; o32 01 /r [386]
ADD reg8,r/m8 ; 02 /r [8086]
ADD reg16,r/m16 ; o16 03 /r [8086]
ADD reg32,r/m32 ; o32 03 /r [386]
ADD r/m8,imm8 ; 80 /0 ib [8086]
ADD r/m16,imm16 ; o16 81 /0 iw [8086]
ADD r/m32,imm32 ; o32 81 /0 id [386]
ADD r/m16,imm8 ; o16 83 /0 ib [8086]
ADD r/m32,imm8 ; o32 83 /0 ib [386]
ADD AL,imm8 ; 04 ib [8086]
ADD AX,imm16 ; o16 05 iw [8086]
ADD EAX,imm32 ; o32 05 id [386]
AND r/m8,reg8 ; 20 /r [8086]
AND r/m16,reg16 ; o16 21 /r [8086]
AND r/m32,reg32 ; o32 21 /r [386]
AND reg8,r/m8 ; 22 /r [8086]
AND reg16,r/m16 ; o16 23 /r [8086]
AND reg32,r/m32 ; o32 23 /r [386]
AND r/m8,imm8 ; 80 /4 ib [8086]
AND r/m16,imm16 ; o16 81 /4 iw [8086]
AND r/m32,imm32 ; o32 81 /4 id [386]
AND r/m16,imm8 ; o16 83 /4 ib [8086]
AND r/m32,imm8 ; o32 83 /4 ib [386]
AND AL,imm8 ; 24 ib [8086]
AND AX,imm16 ; o16 25 iw [8086]
AND EAX,imm32 ; o32 25 id [386]
ARPL r/m16,reg16 ; 63 /r [286,PRIV]
BOUND reg16,mem ; o16 62 /r [186]
BOUND reg32,mem ; o32 62 /r [386]
BSF reg16,r/m16 ; o16 0F BC /r [386]
BSF reg32,r/m32 ; o32 0F BC /r [386]
BSR reg16,r/m16 ; o16 0F BD /r [386]
BSR reg32,r/m32 ; o32 0F BD /r [386]
BSWAP reg32 ; o32 0F C8+r [486]
BT r/m16,reg16 ; o16 0F A3 /r [386]
BT r/m32,reg32 ; o32 0F A3 /r [386]
BT r/m16,imm8 ; o16 0F BA /4 ib [386]
BT r/m32,imm8 ; o32 0F BA /4 ib [386]
BTC r/m16,reg16 ; o16 0F BB /r [386]
BTC r/m32,reg32 ; o32 0F BB /r [386]
BTC r/m16,imm8 ; o16 0F BA /7 ib [386]
BTC r/m32,imm8 ; o32 0F BA /7 ib [386]
BTR r/m16,reg16 ; o16 0F B3 /r [386]
BTR r/m32,reg32 ; o32 0F B3 /r [386]
BTR r/m16,imm8 ; o16 0F BA /6 ib [386]
BTR r/m32,imm8 ; o32 0F BA /6 ib [386]
BTS r/m16,reg16 ; o16 0F AB /r [386]
BTS r/m32,reg32 ; o32 0F AB /r [386]
BTS r/m16,imm ; o16 0F BA /5 ib [386]
BTS r/m32,imm ; o32 0F BA /5 ib [386]
CALL imm ; E8 rw/rd [8086]
CALL imm:imm16 ; o16 9A iw iw [8086]
CALL imm:imm32 ; o32 9A id iw [386]
CALL FAR mem16 ; o16 FF /3 [8086]
CALL FAR mem32 ; o32 FF /3 [386]
CALL r/m16 ; o16 FF /2 [8086]
CALL r/m32 ; o32 FF /2 [386]
CBW ; o16 98 [8086]
CWD ; o16 99 [8086]
CDQ ; o32 99 [386]
CWDE ; o32 98 [386]
CLC ; F8 [8086]
CLD ; FC [8086]
CLI ; FA [8086]
CLTS ; 0F 06 [286,PRIV]
CMC ; F5 [8086]
CMOVcc reg16,r/m16 ; o16 0F 40+cc /r [P6]
CMOVcc reg32,r/m32 ; o32 0F 40+cc /r [P6]
CMP r/m8,reg8 ; 38 /r [8086]
CMP r/m16,reg16 ; o16 39 /r [8086]
CMP r/m32,reg32 ; o32 39 /r [386]
CMP reg8,r/m8 ; 3A /r [8086]
CMP reg16,r/m16 ; o16 3B /r [8086]
CMP reg32,r/m32 ; o32 3B /r [386]
CMP r/m8,imm8 ; 80 /0 ib [8086]
CMP r/m16,imm16 ; o16 81 /0 iw [8086]
CMP r/m32,imm32 ; o32 81 /0 id [386]
DEADCMP r/m16,imm8 ; o16 83 /0 ib [8086]
DEADCMP r/m32,imm8 ; o32 83 /0 ib [386]
CMP AL,imm8 ; 3C ib [8086]
CMP AX,imm16 ; o16 3D iw [8086]
CMP EAX,imm32 ; o32 3D id [386]
CMPSB ; A6 [8086]
CMPSW ; o16 A7 [8086]
CMPSD ; o32 A7 [386]
CMPXCHG r/m8,reg8 ; 0F B0 /r [PENT]
CMPXCHG r/m16,reg16 ; o16 0F B1 /r [PENT]
CMPXCHG r/m32,reg32 ; o32 0F B1 /r [PENT]
CMPXCHG486 r/m8,reg8 ; 0F A6 /r [486,UNDOC]
CMPXCHG486 r/m16,reg16 ; o16 0F A7 /r [486,UNDOC]
CMPXCHG486 r/m32,reg32 ; o32 0F A7 /r [486,UNDOC]
CMPXCHG8B mem ; 0F C7 /1 [PENT]
CPUID ; 0F A2 [PENT]
DAA ; 27 [8086]
DAS ; 2F [8086]
DEC r/m8 ; FE /1 [8086]
DEC r/m16 ; o16 FF /1 [8086]
DEC r/m32 ; o32 FF /1 [386]
DIV r/m8 ; F6 /6 [8086]
DIV r/m16 ; o16 F7 /6 [8086]
DIV r/m32 ; o32 F7 /6 [386]
MMS ; 0F 77 [PENT,MMX]
ENTER imm,imm ; C8 iw ib [186]
F2XM1 ; D9 F0 [8086,FPU]
FABS ; D9 E1 [8086,FPU]
FADD mem32 ; D8 /0 [8086,FPU]
FADD mem64 ; DC /0 [8086,FPU]
FADD fpureg ; D8 C0+r [8086,FPU]
FADD ST0,fpureg ; D8 C0+r [8086,FPU]
FADD TO fpureg ; DC C0+r [8086,FPU]
FADD fpureg,ST0 ; DC C0+r [8086,FPU]
FADDP fpureg ; DE C0+r [8086,FPU]
FADDP fpureg,ST0 ; DE C0+r [8086,FPU]
FBLD mem80 ; DF /4 [8086,FPU]
FBSTP mem80 ; DF /6 [8086,FPU]
FCHS ; D9 E0 [8086,FPU]
FCLEX ; 9B DB E2 [8086,FPU]
FNCLEX ; DB E2 [8086,FPU]
FCMOVB fpureg ; DA C0+r [P6,FPU]
FCMOVB ST0,fpureg ; DA C0+r [P6,FPU]
FCMOVBE fpureg ; DA D0+r [P6,FPU]
FCMOVBE ST0,fpureg ; DA D0+r [P6,FPU]
FCMOVE fpureg ; DA C8+r [P6,FPU]
FCMOVE ST0,fpureg ; DA C8+r [P6,FPU]
FCMOVNB fpureg ; DB C0+r [P6,FPU]
FCMOVNB ST0,fpureg ; DB C0+r [P6,FPU]
FCMOVNBE fpureg ; DB D0+r [P6,FPU]
FCMOVNBE ST0,fpureg ; DB D0+r [P6,FPU]
FCMOVNE fpureg ; DB C8+r [P6,FPU]
FCMOVNE ST0,fpureg ; DB C8+r [P6,FPU]
FCMOVNU fpureg ; DB D8+r [P6,FPU]
FCMOVNU ST0,fpureg ; DB D8+r [P6,FPU]
FCMOVU fpureg ; DA D8+r [P6,FPU]
FCMOVU ST0,fpureg ; DA D8+r [P6,FPU]
FCOM mem32 ; D8 /2 [8086,FPU]
FCOM mem64 ; DC /2 [8086,FPU]
FCOM fpureg ; D8 D0+r [8086,FPU]
FCOM ST0,fpureg ; D8 D0+r [8086,FPU]
FCOMP mem32 ; D8 /3 [8086,FPU]
FCOMP mem64 ; DC /3 [8086,FPU]
FCOMP fpureg ; D8 D8+r [8086,FPU]
FCOMP ST0,fpureg ; D8 D8+r [8086,FPU]
FCOMPP ; DE D9 [8086,FPU]
FCOMI fpureg ; DB F0+r [P6,FPU]
FCOMI ST0,fpureg ; DB F0+r [P6,FPU]
FCOMIP fpureg ; DF F0+r [P6,FPU]
FCOMIP ST0,fpureg ; DF F0+r [P6,FPU]
FCOS ; D9 FF [386,FPU]
FDECSTP ; D9 F6 [8086,FPU]
FDISI ; 9B DB E1 [8086,FPU]
FNDISI ; DB E1 [8086,FPU]
FENI ; 9B DB E0 [8086,FPU]
FNENI ; DB E0 [8086,FPU]
FDIV mem32 ; D8 /6 [8086,FPU]
FDIV mem64 ; DC /6 [8086,FPU]
FDIV fpureg ; D8 F0+r [8086,FPU]
FDIV ST0,fpureg ; D8 F0+r [8086,FPU]
FDIV TO fpureg ; DC F8+r [8086,FPU]
FDIV fpureg,ST0 ; DC F8+r [8086,FPU]
FDIVR mem32 ; D8 /0 [8086,FPU]
FDIVR mem64 ; DC /0 [8086,FPU]
FDIVR fpureg ; D8 F8+r [8086,FPU]
FDIVR ST0,fpureg ; D8 F8+r [8086,FPU]
FDIVR TO fpureg ; DC F0+r [8086,FPU]
FDIVR fpureg,ST0 ; DC F0+r [8086,FPU]
FDIVP fpureg ; DE F8+r [8086,FPU]
FDIVP fpureg,ST0 ; DE F8+r [8086,FPU]
FDIVRP fpureg ; DE F0+r [8086,FPU]
FDIVRP fpureg,ST0 ; DE F0+r [8086,FPU]
FFREE fpureg ; DD C0+r [8086,FPU]
FIADD mem16 ; DE /0 [8086,FPU]
FIADD mem32 ; DA /0 [8086,FPU]
FICOM mem16 ; DE /2 [8086,FPU]
FICOM mem32 ; DA /2 [8086,FPU]
FICOMP mem16 ; DE /3 [8086,FPU]
FICOMP mem32 ; DA /3 [8086,FPU]
FIDIV mem16 ; DE /6 [8086,FPU]
FIDIV mem32 ; DA /6 [8086,FPU]
FIDIVR mem16 ; DE /0 [8086,FPU]
FIDIVR mem32 ; DA /0 [8086,FPU]
FILD mem16 ; DF /0 [8086,FPU]
FILD mem32 ; DB /0 [8086,FPU]
FILD mem64 ; DF /5 [8086,FPU]
FIST mem16 ; DF /2 [8086,FPU]
FIST mem32 ; DB /2 [8086,FPU]
FISTP mem16 ; DF /3 [8086,FPU]
FISTP mem32 ; DB /3 [8086,FPU]
FISTP mem64 ; DF /0 [8086,FPU]
FIMUL mem16 ; DE /1 [8086,FPU]
FIMUL mem32 ; DA /1 [8086,FPU]
FINCSTP ; D9 F7 [8086,FPU]
FINIT ; 9B DB E3 [8086,FPU]
FNINIT ; DB E3 [8086,FPU]
FISUB mem16 ; DE /4 [8086,FPU]
FISUB mem32 ; DA /4 [8086,FPU]
FISUBR mem16 ; DE /5 [8086,FPU]
FISUBR mem32 ; DA /5 [8086,FPU]
FLD mem32 ; D9 /0 [8086,FPU]
FLD mem64 ; DD /0 [8086,FPU]
FLD mem80 ; DB /5 [8086,FPU]
FLD fpureg ; D9 C0+r [8086,FPU]
FLD1 ; D9 E8 [8086,FPU]
FLDL2E ; D9 EA [8086,FPU]
FLDL2T ; D9 E9 [8086,FPU]
FLDLG2 ; D9 EC [8086,FPU]
FLDLN2 ; D9 ED [8086,FPU]
FLDPI ; D9 EB [8086,FPU]
FLDZ ; D9 EE [8086,FPU]
FLDCW mem16 ; D9 /5 [8086,FPU]
FLDENV mem ; D9 /4 [8086,FPU]
FMUL mem32 ; D8 /1 [8086,FPU]
FMUL mem64 ; DC /1 [8086,FPU]
FMUL fpureg ; D8 C8+r [8086,FPU]
FMUL ST0,fpureg ; D8 C8+r [8086,FPU]
FMUL TO fpureg ; DC C8+r [8086,FPU]
FMUL fpureg,ST0 ; DC C8+r [8086,FPU]
FMULP fpureg ; DE C8+r [8086,FPU]
FMULP fpureg,ST0 ; DE C8+r [8086,FPU]
FNOP ; D9 D0 [8086,FPU]
FPATAN ; D9 F3 [8086,FPU]
FPTAN ; D9 F2 [8086,FPU]
FPREM ; D9 F8 [8086,FPU]
FPREM1 ; D9 F5 [386,FPU]
FRNDINT ; D9 FC [8086,FPU]
FSAVE mem ; 9B DD /6 [8086,FPU]
FNSAVE mem ; DD /6 [8086,FPU]
FRSTOR mem ; DD /4 [8086,FPU]
FSCALE ; D9 FD [8086,FPU]
FSETPM ; DB E4 [286,FPU]
FSIN ; D9 FE [386,FPU]
FSINCOS ; D9 FB [386,FPU]
FSQRT ; D9 FA [8086,FPU]
FST mem32 ; D9 /2 [8086,FPU]
FST mem64 ; DD /2 [8086,FPU]
FST fpureg ; DD D0+r [8086,FPU]
FSTP mem32 ; D9 /3 [8086,FPU]
FSTP mem64 ; DD /3 [8086,FPU]
FSTP mem80 ; DB /0 [8086,FPU]
FSTP fpureg ; DD D8+r [8086,FPU]
FSTCW mem16 ; 9B D9 /0 [8086,FPU]
FNSTCW mem16 ; D9 /0 [8086,FPU]
FSTENV mem ; 9B D9 /6 [8086,FPU]
FNSTENV mem ; D9 /6 [8086,FPU]
FSTSW mem16 ; 9B DD /0 [8086,FPU]
FSTSW AX ; 9B DF E0 [286,FPU]
FNSTSW mem16 ; DD /0 [8086,FPU]
FNSTSW AX ; DF E0 [286,FPU]
FSUB mem32 ; D8 /4 [8086,FPU]
FSUB mem64 ; DC /4 [8086,FPU]
FSUB fpureg ; D8 E0+r [8086,FPU]
FSUB ST0,fpureg ; D8 E0+r [8086,FPU]
FSUB TO fpureg ; DC E8+r [8086,FPU]
FSUB fpureg,ST0 ; DC E8+r [8086,FPU]
FSUBR mem32 ; D8 /5 [8086,FPU]
FSUBR mem64 ; DC /5 [8086,FPU]
FSUBR fpureg ; D8 E8+r [8086,FPU]
FSUBR ST0,fpureg ; D8 E8+r [8086,FPU]
FSUBR TO fpureg ; DC E0+r [8086,FPU]
FSUBR fpureg,ST0 ; DC E0+r [8086,FPU]
FSUBP fpureg ; DE E8+r [8086,FPU]
FSUBP fpureg,ST0 ; DE E8+r [8086,FPU]
FSUBRP fpureg ; DE E0+r [8086,FPU]
FSUBRP fpureg,ST0 ; DE E0+r [8086,FPU]
FTST ; D9 E4 [8086,FPU]
FUCOM fpureg ; DD E0+r [386,FPU]
FUCOM ST0,fpureg ; DD E0+r [386,FPU]
FUCOMP fpureg ; DD E8+r [386,FPU]
FUCOMP ST0,fpureg ; DD E8+r [386,FPU]
FUCOMPP ; DA E9 [386,FPU]
FUCOMI fpureg ; DB E8+r [P6,FPU]
FUCOMI ST0,fpureg ; DB E8+r [P6,FPU]
FUCOMIP fpureg ; DF E8+r [P6,FPU]
FUCOMIP ST0,fpureg ; DF E8+r [P6,FPU]
FXAM ; D9 E5 [8086,FPU]
FXCH ; D9 C9 [8086,FPU]
FXCH fpureg ; D9 C8+r [8086,FPU]
FXCH fpureg,ST0 ; D9 C8+r [8086,FPU]
FXCH ST0,fpureg ; D9 C8+r [8086,FPU]
FXTRACT ; D9 F4 [8086,FPU]
FYL2X ; D9 F1 [8086,FPU]
FYL2XP1 ; D9 F9 [8086,FPU]
HLT ; F4 [8086]
IBTS r/m16,reg16 ; o16 0F A7 /r [386,UNDOC]
IBTS r/m32,reg32 ; o32 0F A7 /r [386,UNDOC]
IDIV r/m8 ; F6 /7 [8086]
IDIV r/m16 ; o16 F7 /7 [8086]
IDIV r/m32 ; o32 F7 /7 [386]
IMUL r/m8 ; F6 /5 [8086]
IMUL r/m16 ; o16 F7 /5 [8086]
IMUL r/m32 ; o32 F7 /5 [386]
IMUL reg16,r/m16 ; o16 0F AF /r [386]
IMUL reg32,r/m32 ; o32 0F AF /r [386]
IMUL reg16,imm8 ; o16 6B /r ib [286]
IMUL reg16,imm16 ; o16 69 /r iw [286]
IMUL reg32,imm8 ; o32 6B /r ib [386]
IMUL reg32,imm32 ; o32 69 /r id [386]
IMUL reg16,r/m16,imm8 ; o16 6B /r ib [286]
IMUL reg16,r/m16,imm16 ; o16 69 /r iw [286]
IMUL reg32,r/m32,imm8 ; o32 6B /r ib [386]
IMUL reg32,r/m32,imm32 ; o32 69 /r id [386]
IN AL,imm8 ; E4 ib [8086]
IN AX,imm8 ; o16 E5 ib [8086]
IN EAX,imm8 ; o32 E5 ib [386]
IN AL,DX ; EC [8086]
IN AX,DX ; o16 ED [8086]
IN EAX,DX ; o32 ED [386]
INC r/m8 ; FE /0 [8086]
INC r/m16 ; o16 FF /0 [8086]
INC r/m32 ; o32 FF /0 [386]
INSB ; 6C [186]
INSW ; o16 6D [186]
INSD ; o32 6D [386]
INT imm8 ; CD ib [8086]
INT1 ; F1 [P6]
ICEBP ; F1 [P6]
INT01 ; F1 [P6]
INT3 ; CC [8086]
INTO ; CE [8086]
INVD ; 0F 08 [486]
INVLPG mem ; 0F 01 /0 [486]
IRET ; CF [8086]
IRETW ; o16 CF [8086]
IRETD ; o32 CF [386]
JCXZ imm ; o16 E3 rb [8086]
JECXZ imm ; o32 E3 rb [386]
JMP imm ; E9 rw/rd [8086]
JMP SHORT imm ; EB rb [8086]
JMP imm:imm16 ; o16 EA iw iw [8086]
JMP imm:imm32 ; o32 EA id iw [386]
JMP FAR mem ; o16 FF /5 [8086]
JMP FAR mem ; o32 FF /5 [386]
JMP r/m16 ; o16 FF /4 [8086]
JMP r/m32 ; o32 FF /4 [386]
Jcc imm ; 70+cc rb [8086]
Jcc NEAR imm ; 0F 80+cc rw/rd [386]
LAHF ; 9F [8086]
LAR reg16,r/m16 ; o16 0F 02 /r [286,PRIV]
LAR reg32,r/m32 ; o32 0F 02 /r [286,PRIV]
LDS reg16,mem ; o16 C5 /r [8086]
LDS reg32,mem ; o32 C5 /r [8086]
LES reg16,mem ; o16 C4 /r [8086]
LES reg32,mem ; o32 C4 /r [8086]
LFS reg16,mem ; o16 0F B4 /r [386]
LFS reg32,mem ; o32 0F B4 /r [386]
LGS reg16,mem ; o16 0F B5 /r [386]
LGS reg32,mem ; o32 0F B5 /r [386]
LSS reg16,mem ; o16 0F B2 /r [386]
LSS reg32,mem ; o32 0F B2 /r [386]
LEA reg16,mem ; o16 8D /r [8086]
LEA reg32,mem ; o32 8D /r [8086]
LEAVE ; C9 [186]
LGDT mem ; 0F 01 /2 [286,PRIV]
LIDT mem ; 0F 01 /3 [286,PRIV]
LLDT r/m16 ; 0F 00 /2 [286,PRIV]
LMSW r/m16 ; 0F 01 /6 [286,PRIV]
LOADALL ; 0F 07 [386,UNDOC]
LOADALL286 ; 0F 05 [286,UNDOC]
LODSB ; AC [8086]
LODSW ; o16 AD [8086]
LODSD ; o32 AD [386]
LOOP imm ; E2 rb [8086]
LOOP imm,CX ; a16 E2 rb [8086]
LOOP imm,ECX ; a32 E2 rb [386]
LOOPE imm ; E1 rb [8086]
LOOPE imm,CX ; a16 E1 rb [8086]
LOOPE imm,ECX ; a32 E1 rb [386]
LOOPZ imm ; E1 rb [8086]
LOOPZ imm,CX ; a16 E1 rb [8086]
LOOPZ imm,ECX ; a32 E1 rb [386]
LOOPNE imm ; E0 rb [8086]
LOOPNE imm,CX ; a16 E0 rb [8086]
LOOPNE imm,ECX ; a32 E0 rb [386]
LOOPNZ imm ; E0 rb [8086]
LOOPNZ imm,CX ; a16 E0 rb [8086]
LOOPNZ imm,ECX ; a32 E0 rb [386]
LSL reg16,r/m16 ; o16 0F 03 /r [286,PRIV]
LSL reg32,r/m32 ; o32 0F 03 /r [286,PRIV]
LTR r/m16 ; 0F 00 /3 [286,PRIV]
MOV r/m8,reg8 ; 88 /r [8086]
MOV r/m16,reg16 ; o16 89 /r [8086]
MOV r/m32,reg32 ; o32 89 /r [386]
MOV reg8,r/m8 ; 8A /r [8086]
MOV reg16,r/m16 ; o16 8B /r [8086]
MOV reg32,r/m32 ; o32 8B /r [386]
MOV reg8,imm8 ; B0+r ib [8086]
MOV reg16,imm16 ; o16 B8+r iw [8086]
MOV reg32,imm32 ; o32 B8+r id [386]
MOV r/m8,imm8 ; C6 /0 ib [8086]
MOV r/m16,imm16 ; o16 C7 /0 iw [8086]
MOV r/m32,imm32 ; o32 C7 /0 id [386]
MOV AL,memoffs8 ; A0 ow/od [8086]
MOV AX,memoffs16 ; o16 A1 ow/od [8086]
MOV EAX,memoffs32 ; o32 A1 ow/od [386]
MOV memoffs8,AL ; A2 ow/od [8086]
MOV memoffs16,AX ; o16 A3 ow/od [8086]
MOV memoffs32,EAX ; o32 A3 ow/od [386]
MOV r/m16,segreg ; o16 8C /r [8086]
MOV r/m32,segreg ; o32 8C /r [386]
MOV segreg,r/m16 ; o16 8E /r [8086]
MOV segreg,r/m32 ; o32 8E /r [386]
MOV reg32,CR0/2/3/4 ; 0F 20 /r [386]
MOV reg32,DR0/1/2/3/6/7 ; 0F 21 /r [386]
MOV reg32,TR3/4/5/6/7 ; 0F 24 /r [386]
MOV CR0/2/3/4,reg32 ; 0F 22 /r [386]
MOV DR0/1/2/3/6/7,reg32 ; 0F 23 /r [386]
MOV TR3/4/5/6/7,reg32 ; 0F 26 /r [386]
MOVD mmxreg,r/m32 ; 0F 6E /r [PENT,MMX]
MOVD r/m32,mmxreg ; 0F 7E /r [PENT,MMX]
MOVQ mmxreg,r/m64 ; 0F 6F /r [PENT,MMX]
MOVQ r/m64,mmxreg ; 0F 7F /r [PENT,MMX]
MOVSB ; A4 [8086]
MOVSW ; o16 A5 [8086]
MOVSD ; o32 A5 [386]
MOVSX reg16,r/m8 ; o16 0F BE /r [386]
MOVSX reg32,r/m8 ; o32 0F BE /r [386]
MOVSX reg32,r/m16 ; o32 0F BF /r [386]
MOVZX reg16,r/m8 ; o16 0F B6 /r [386]
MOVZX reg32,r/m8 ; o32 0F B6 /r [386]
MOVZX reg32,r/m16 ; o32 0F B7 /r [386]
MUL r/m8 ; F6 /4 [8086]
MUL r/m16 ; o16 F7 /4 [8086]
MUL r/m32 ; o32 F7 /4 [386]
NEG r/m8 ; F6 /3 [8086]
NEG r/m16 ; o16 F7 /3 [8086]
NEG r/m32 ; o32 F7 /3 [386]
NOT r/m8 ; F6 /2 [8086]
NOT r/m16 ; o16 F7 /2 [8086]
NOT r/m32 ; o32 F7 /2 [386]
NOP ; 90 [8086]
OR r/m8,reg8 ; 08 /r [8086]
OR r/m16,reg16 ; o16 09 /r [8086]
OR r/m32,reg32 ; o32 09 /r [386]
OR reg8,r/m8 ; 0A /r [8086]
OR reg16,r/m16 ; o16 0B /r [8086]
OR reg32,r/m32 ; o32 0B /r [386]
OR r/m8,imm8 ; 80 /1 ib [8086]
OR r/m16,imm16 ; o16 81 /1 iw [8086]
OR r/m32,imm32 ; o32 81 /1 id [386]
OR r/m16,imm8 ; o16 83 /1 ib [8086]
OR r/m32,imm8 ; o32 83 /1 ib [386]
OR AL,imm8 ; 0C ib [8086]
OR AX,imm16 ; o16 0D iw [8086]
OR EAX,imm32 ; o32 0D id [386]
OUT imm8,AL ; E6 ib [8086]
OUT imm8,AX ; o16 E7 ib [8086]
OUT imm8,EAX ; o32 E7 ib [386]
OUT DX,AL ; EE [8086]
OUT DX,AX ; o16 EF [8086]
OUT DX,EAX ; o32 EF [386]
OUTSB ; 6E [186]
OUTSW ; o16 6F [186]
OUTSD ; o32 6F [386]
PACKSSDW mmxreg,r/m64 ; 0F 6B /r [PENT,MMX]
PACKSSWB mmxreg,r/m64 ; 0F 63 /r [PENT,MMX]
PACKUSWB mmxreg,r/m64 ; 0F 67 /r [PENT,MMX]
PADDB mmxreg,r/m64 ; 0F FC /r [PENT,MMX]
PADDW mmxreg,r/m64 ; 0F FD /r [PENT,MMX]
PADDD mmxreg,r/m64 ; 0F FE /r [PENT,MMX]
PADDSB mmxreg,r/m64 ; 0F EC /r [PENT,MMX]
PADDSW mmxreg,r/m64 ; 0F ED /r [PENT,MMX]
PADDUSB mmxreg,r/m64 ; 0F DC /r [PENT,MMX]
PADDUSW mmxreg,r/m64 ; 0F DD /r [PENT,MMX]
PADDSIW mmxreg,r/m64 ; 0F 51 /r [CYRIX,MMX]
PAND mmxreg,r/m64 ; 0F DB /r [PENT,MMX]
PANDN mmxreg,r/m64 ; 0F DF /r [PENT,MMX]
PAVEB mmxreg,r/m64 ; 0F 50 /r [CYRIX,MMX]
PCMPEQB mmxreg,r/m64 ; 0F 74 /r [PENT,MMX]
PCMPEQW mmxreg,r/m64 ; 0F 75 /r [PENT,MMX]
PCMPEQD mmxreg,r/m64 ; 0F 76 /r [PENT,MMX]
PCMPGTB mmxreg,r/m64 ; 0F 64 /r [PENT,MMX]
PCMPGTW mmxreg,r/m64 ; 0F 65 /r [PENT,MMX]
PCMPGTD mmxreg,r/m64 ; 0F 66 /r [PENT,MMX]
PDISTIB mmxreg,mem64 ; 0F 54 /r [CYRIX,MMX]
PMACHRIW mmxreg,mem64 ; 0F 5E /r [CYRIX,MMX]
PMADDWD mmxreg,r/m64 ; 0F F5 /r [PENT,MMX]
PMAGW mmxreg,r/m64 ; 0F 52 /r [CYRIX,MMX]
PMULHRW mmxreg,r/m64 ; 0F 59 /r [CYRIX,MMX]
PMULHRIW mmxreg,r/m64 ; 0F 5D /r [CYRIX,MMX]
PMULHW mmxreg,r/m64 ; 0F E5 /r [PENT,MMX]
PMULLW mmxreg,r/m64 ; 0F D5 /r [PENT,MMX]
PMVZB mmxreg,mem64 ; 0F 58 /r [CYRIX,MMX]
PMVNZB mmxreg,mem64 ; 0F 5A /r [CYRIX,MMX]
PMVLZB mmxreg,mem64 ; 0F 5B /r [CYRIX,MMX]
PMVGEZB mmxreg,mem64 ; 0F 5C /r [CYRIX,MMX]
POP reg16 ; o16 58+r [8086]
POP reg32 ; o32 58+r [386]
POP r/m16 ; o16 8F /0 [8086]
POP r/m32 ; o32 8F /0 [386]
POP CS ; 0F [8086,UNDOC]
POP DS ; 1F [8086]
POP ES ; 07 [8086]
POP SS ; 17 [8086]
POP FS ; 0F A1 [386]
POP GS ; 0F A9 [386]
POPA ; 61 [186]
POPAW ; o16 61 [186]
POPAD ; o32 61 [386]
POPF ; 9D [186]
POPFW ; o16 9D [186]
POPFD ; o32 9D [386]
POR mmxreg,r/m64 ; 0F EB /r [PENT,MMX]
PSLLW mmxreg,r/m64 ; 0F F1 /r [PENT,MMX]
PSLLW mmxreg,imm8 ; 0F 71 /6 ib [PENT,MMX]
PSLLD mmxreg,r/m64 ; 0F F2 /r [PENT,MMX]
PSLLD mmxreg,imm8 ; 0F 72 /6 ib [PENT,MMX]
PSLLQ mmxreg,r/m64 ; 0F F3 /r [PENT,MMX]
PSLLQ mmxreg,imm8 ; 0F 73 /6 ib [PENT,MMX]
PSRAW mmxreg,r/m64 ; 0F E1 /r [PENT,MMX]
PSRAW mmxreg,imm8 ; 0F 71 /4 ib [PENT,MMX]
PSRAD mmxreg,r/m64 ; 0F E2 /r [PENT,MMX]
PSRAD mmxreg,imm8 ; 0F 72 /4 ib [PENT,MMX]
PSRLW mmxreg,r/m64 ; 0F D1 /r [PENT,MMX]
PSRLW mmxreg,imm8 ; 0F 71 /2 ib [PENT,MMX]
PSRLD mmxreg,r/m64 ; 0F D2 /r [PENT,MMX]
PSRLD mmxreg,imm8 ; 0F 72 /2 ib [PENT,MMX]
PSRLQ mmxreg,r/m64 ; 0F D3 /r [PENT,MMX]
PSRLQ mmxreg,imm8 ; 0F 73 /2 ib [PENT,MMX]
PSUBB mmxreg,r/m64 ; 0F F8 /r [PENT,MMX]
PSUBW mmxreg,r/m64 ; 0F F9 /r [PENT,MMX]
PSUBD mmxreg,r/m64 ; 0F FA /r [PENT,MMX]
PSUBSB mmxreg,r/m64 ; 0F E8 /r [PENT,MMX]
PSUBSW mmxreg,r/m64 ; 0F E9 /r [PENT,MMX]
PSUBUSB mmxreg,r/m64 ; 0F D8 /r [PENT,MMX]
PSUBUSW mmxreg,r/m64 ; 0F D9 /r [PENT,MMX]
PSUBSIW mmxreg,r/m64 ; 0F 55 /r [CYRIX,MMX]
PUNPCKHBW mmxreg,r/m64 ; 0F 68 /r [PENT,MMX]
PUNPCKHWD mmxreg,r/m64 ; 0F 69 /r [PENT,MMX]
PUNPCKHDQ mmxreg,r/m64 ; 0F 6A /r [PENT,MMX]
PUNPCKLBW mmxreg,r/m64 ; 0F 60 /r [PENT,MMX]
PUNPCKLWD mmxreg,r/m64 ; 0F 61 /r [PENT,MMX]
PUNPCKLDQ mmxreg,r/m64 ; 0F 62 /r [PENT,MMX]
PUSH reg16 ; o16 50+r [8086]
PUSH reg32 ; o32 50+r [386]
PUSH r/m16 ; o16 FF /6 [8086]
PUSH r/m32 ; o32 FF /6 [386]
PUSH CS ; 0E [8086]
PUSH DS ; 1E [8086]
PUSH ES ; 06 [8086]
PUSH SS ; 16 [8086]
PUSH FS ; 0F A0 [386]
PUSH GS ; 0F A8 [386]
PUSH imm8 ; 6A ib [286]
PUSH imm16 ; o16 68 iw [286]
PUSH imm32 ; o32 68 id [386]
PUSHA ; 60 [186]
PUSHAD ; o32 60 [386]
PUSHAW ; o16 60 [186]
PUSHF ; 9C [186]
PUSHFD ; o32 9C [386]
PUSHFW ; o16 9C [186]
PXOR mmxreg,r/m64 ; 0F EF /r [PENT,MMX]
RCL r/m8,1 ; D0 /2 [8086]
RCL r/m8,CL ; D2 /2 [8086]
RCL r/m8,imm8 ; C0 /2 ib [286]
RCL r/m16,1 ; o16 D1 /2 [8086]
RCL r/m16,CL ; o16 D3 /2 [8086]
RCL r/m16,imm8 ; o16 C1 /2 ib [286]
RCL r/m32,1 ; o32 D1 /2 [386]
RCL r/m32,CL ; o32 D3 /2 [386]
RCL r/m32,imm8 ; o32 C1 /2 ib [386]
RCR r/m8,1 ; D0 /3 [8086]
RCR r/m8,CL ; D2 /3 [8086]
RCR r/m8,imm8 ; C0 /3 ib [286]
RCR r/m16,1 ; o16 D1 /3 [8086]
RCR r/m16,CL ; o16 D3 /3 [8086]
RCR r/m16,imm8 ; o16 C1 /3 ib [286]
RCR r/m32,1 ; o32 D1 /3 [386]
RCR r/m32,CL ; o32 D3 /3 [386]
RCR r/m32,imm8 ; o32 C1 /3 ib [386]
RDMSR ; 0F 32 [PENT]
RDPMC ; 0F 33 [P6]
RDTSC ; 0F 31 [PENT]
RET ; C3 [8086]
RET imm16 ; C2 iw [8086]
RETF ; CB [8086]
RETF imm16 ; CA iw [8086]
RETN ; C3 [8086]
RETN imm16 ; C2 iw [8086]
ROL r/m8,1 ; D0 /0 [8086]
ROL r/m8,CL ; D2 /0 [8086]
ROL r/m8,imm8 ; C0 /0 ib [286]
ROL r/m16,1 ; o16 D1 /0 [8086]
ROL r/m16,CL ; o16 D3 /0 [8086]
ROL r/m16,imm8 ; o16 C1 /0 ib [286]
ROL r/m32,1 ; o32 D1 /0 [386]
ROL r/m32,CL ; o32 D3 /0 [386]
ROL r/m32,imm8 ; o32 C1 /0 ib [386]
ROR r/m8,1 ; D0 /1 [8086]
ROR r/m8,CL ; D2 /1 [8086]
ROR r/m8,imm8 ; C0 /1 ib [286]
ROR r/m16,1 ; o16 D1 /1 [8086]
ROR r/m16,CL ; o16 D3 /1 [8086]
ROR r/m16,imm8 ; o16 C1 /1 ib [286]
ROR r/m32,1 ; o32 D1 /1 [386]
ROR r/m32,CL ; o32 D3 /1 [386]
ROR r/m32,imm8 ; o32 C1 /1 ib [386]
RSM ; 0F AA [PENT]
SAHF ; 9E [8086]
SAL r/m8,1 ; D0 /4 [8086]
SAL r/m8,CL ; D2 /4 [8086]
SAL r/m8,imm8 ; C0 /4 ib [286]
SAL r/m16,1 ; o16 D1 /4 [8086]
SAL r/m16,CL ; o16 D3 /4 [8086]
SAL r/m16,imm8 ; o16 C1 /4 ib [286]
SAL r/m32,1 ; o32 D1 /4 [386]
SAL r/m32,CL ; o32 D3 /4 [386]
SAL r/m32,imm8 ; o32 C1 /4 ib [386]
SAR r/m8,1 ; D0 /0 [8086]
SAR r/m8,CL ; D2 /0 [8086]
SAR r/m8,imm8 ; C0 /0 ib [286]
SAR r/m16,CL ; o16 D3 /0 [8086]
SAR r/m16,imm8 ; o16 C1 /0 ib [286]
SAR r/m32,CL ; o32 D3 /0 [386]
SAR r/m32,imm8 ; o32 C1 /0 ib [386]
SALC ; D6 [8086,UNDOC]
SBB r/m8,reg8 ; 18 /r [8086]
SBB r/m16,reg16 ; o16 19 /r [8086]
SBB r/m32,reg32 ; o32 19 /r [386]
SBB reg8,r/m8 ; 1A /r [8086]
SBB reg16,r/m16 ; o16 1B /r [8086]
SBB reg32,r/m32 ; o32 1B /r [386]
SBB r/m8,imm8 ; 80 /3 ib [8086]
SBB r/m16,imm16 ; o16 81 /3 iw [8086]
SBB r/m32,imm32 ; o32 81 /3 id [386]
SBB r/m16,imm8 ; o16 83 /3 ib [8086]
SBB r/m32,imm8 ; o32 83 /3 ib [8086]
SBB AL,imm8 ; 1C ib [8086]
SBB AX,imm16 ; o16 1D iw [8086]
SBB EAX,imm32 ; o32 1D id [386]
SCASB ; AE [8086]
SCASW ; o16 AF [8086]
SCASD ; o32 AF [386]
SETcc r/m8 ; 0F 90+cc /2 [386]
SGDT mem ; 0F 01 /0 [286,PRIV]
SIDT mem ; 0F 01 /1 [286,PRIV]
SLDT r/m16 ; 0F 00 /0 [286,PRIV]
SHL r/m8,1 ; D0 /4 [8086]
SHL r/m8,CL ; D2 /4 [8086]
SHL r/m8,imm8 ; C0 /4 ib [286]
SHL r/m16,1 ; o16 D1 /4 [8086]
SHL r/m16,CL ; o16 D3 /4 [8086]
SHL r/m16,imm8 ; o16 C1 /4 ib [286]
SHL r/m32,1 ; o32 D1 /4 [386]
SHL r/m32,CL ; o32 D3 /4 [386]
SHL r/m32,imm8 ; o32 C1 /4 ib [386]
SHR r/m8,1 ; D0 /5 [8086]
SHR r/m8,CL ; D2 /5 [8086]
SHR r/m8,imm8 ; C0 /5 ib [286]
SHR r/m16,1 ; o16 D1 /5 [8086]
SHR r/m16,CL ; o16 D3 /5 [8086]
SHR r/m16,imm8 ; o16 C1 /5 ib [286]
SHR r/m32,1 ; o32 D1 /5 [386]
SHR r/m32,CL ; o32 D3 /5 [386]
SHR r/m32,imm8 ; o32 C1 /5 ib [386]
SHLD r/m16,reg16,imm8 ; o16 0F A4 /r ib [386]
SHLD r/m16,reg32,imm8 ; o32 0F A4 /r ib [386]
SHLD r/m16,reg16,CL ; o16 0F A5 /r [386]
SHLD r/m16,reg32,CL ; o32 0F A5 /r [386]
SHRD r/m16,reg16,imm8 ; o16 0F AC /r ib [386]
SHRD r/m32,reg32,imm8 ; o32 0F AC /r ib [386]
SHRD r/m16,reg16,CL ; o16 0F AD /r [386]
SHRD r/m32,reg32,CL ; o32 0F AD /r [386]
SMI ; F1 [386,UNDOC]
SMSW r/m16 ; 0F 01 /4 [286,PRIV]
STC ; F9 [8086]
STD ; FD [8086]
STI ; FB [8086]
STOSB ; AA [8086]
STOSW ; o16 AB [8086]
STOSD ; o32 AB [386]
STR r/m16 ; 0F 00 /1 [286,PRIV]
SUB r/m8,reg8 ; 28 /r [8086]
SUB r/m16,reg16 ; o16 29 /r [8086]
SUB r/m32,reg32 ; o32 29 /r [386]
SUB reg8,r/m8 ; 2A /r [8086]
SUB reg16,r/m16 ; o16 2B /r [8086]
SUB reg32,r/m32 ; o32 2B /r [386]
SUB r/m8,imm8 ; 80 /5 ib [8086]
SUB r/m16,imm16 ; o16 81 /5 iw [8086]
SUB r/m32,imm32 ; o32 81 /5 id [386]
SUB r/m16,imm8 ; o16 83 /5 ib [8086]
SUB r/m32,imm8 ; o32 83 /5 ib [386]
SUB AL,imm8 ; 2C ib [8086]
SUB AX,imm16 ; o16 2D iw [8086]
SUB EAX,imm32 ; o32 2D id [386]
TEST r/m8,reg8 ; 84 /r [8086]
TEST r/m16,reg16 ; o16 85 /r [8086]
TEST r/m32,reg32 ; o32 85 /r [386]
TEST r/m8,imm8 ; F6 /7 ib [8086]
TEST r/m16,imm16 ; o16 F7 /7 iw [8086]
TEST r/m32,imm32 ; o32 F7 /7 id [386]
TEST AL,imm8 ; A8 ib [8086]
TEST AX,imm16 ; o16 A9 iw [8086]
TEST EAX,imm32 ; o32 A9 id [386]
UMOV r/m8,reg8 ; 0F 10 /r [386,UNDOC]
UMOV r/m16,reg16 ; o16 0F 11 /r [386,UNDOC]
UMOV r/m32,reg32 ; o32 0F 11 /r [386,UNDOC]
UMOV reg8,r/m8 ; 0F 12 /r [386,UNDOC]
UMOV reg16,r/m16 ; o16 0F 13 /r [386,UNDOC]
UMOV reg32,r/m32 ; o32 0F 13 /r [386,UNDOC]
VERR r/m16 ; 0F 00 /4 [286,PRIV]
VERW r/m16 ; 0F 00 /5 [286,PRIV]
WAIT ; 9B [8086]
WBINVD ; 0F 09 [486]
WRMSR ; 0F 30 [PENT]
XADD r/m8,reg8 ; 0F C0 /r [486]
XADD r/m16,reg16 ; o16 0F C1 /r [486]
XADD r/m32,reg32 ; o32 0F C1 /r [486]
XBTS reg16,r/m16 ; o16 0F A6 /r [386,UNDOC]
XBTS reg32,r/m32 ; o32 0F A6 /r [386,UNDOC]
XCHG reg8,r/m8 ; 86 /r [8086]
XCHG reg16,r/m8 ; o16 87 /r [8086]
XCHG reg32,r/m32 ; o32 87 /r [386]
XCHG r/m8,reg8 ; 86 /r [8086]
XCHG r/m16,reg16 ; o16 87 /r [8086]
XCHG r/m32,reg32 ; o32 87 /r [386]
XCHG AX,reg16 ; o16 90+r [8086]
XCHG EAX,reg32 ; o32 90+r [386]
XCHG reg16,AX ; o16 90+r [8086]
XCHG reg32,EAX ; o32 90+r [386]
XLATB ; D7 [8086]
XOR r/m8,reg8 ; 30 /r [8086]
XOR r/m16,reg16 ; o16 31 /r [8086]
XOR r/m32,reg32 ; o32 31 /r [386]
XOR reg8,r/m8 ; 32 /r [8086]
XOR reg16,r/m16 ; o16 33 /r [8086]
XOR reg32,r/m32 ; o32 33 /r [386]
XOR r/m8,imm8 ; 80 /6 ib [8086]
XOR r/m16,imm16 ; o16 81 /6 iw [8086]
XOR r/m32,imm32 ; o32 81 /6 id [386]
XOR r/m16,imm8 ; o16 83 /6 ib [8086]
XOR r/m32,imm8 ; o32 83 /6 ib [386]
XOR AL,imm8 ; 34 ib [8086]
XOR AX,imm16 ; o16 35 iw [8086]
XOR EAX,imm32 ; o32 35 id [386]

Test details

Test 1

Group: 1

Verdict: ACCEPTED

input
1

correct output
#

user output
#

Test 2

Group: 2

Verdict: ACCEPTED

input
2

correct output
##
#.

user output
##
#.

Test 3

Group: 3

Verdict: ACCEPTED

input
3

correct output
####
#.#.
##..
#..#

user output
####
#.#.
##..
#..#

Test 4

Group: 4

Verdict: ACCEPTED

input
4

correct output
########
#.#.#.#.
##..##..
#..##..#
####....
...

user output
########
#.#.#.#.
##..##..
#..##..#
####....
...

Test 5

Group: 5

Verdict: ACCEPTED

input
5

correct output
################
#.#.#.#.#.#.#.#.
##..##..##..##..
#..##..##..##..#
####....####....
...

user output
################
#.#.#.#.#.#.#.#.
##..##..##..##..
#..##..##..##..#
####....####....
...

Test 6

Group: 6

Verdict: ACCEPTED

input
6

correct output
##############################...

user output
##############################...

Test 7

Group: 7

Verdict: ACCEPTED

input
7

correct output
##############################...

user output
##############################...

Test 8

Group: 8

Verdict: ACCEPTED

input
8

correct output
##############################...

user output
##############################...

Test 9

Group: 9

Verdict: ACCEPTED

input
9

correct output
##############################...

user output
##############################...

Test 10

Group: 10

Verdict: ACCEPTED

input
10

correct output
##############################...

user output
##############################...