def _impl(inst, offset, operand): if isinstance(operand, Label): distance = operand.offset - offset - 6 inst.chr(0x0f) inst.chr(opcode) inst.pack('i', distance) else: raise AssemblyError('unsupported operand: %s' % operand)
def not_(inst, register, width=32): if width == 32: inst.chr(0xf7) inst.modrm(3, 2, register) elif width == 8: inst.chr(0xf6) inst.modrm(3, 2, register) else: raise AssemblyError('unsupported bit width: %s' % width)
def cmp(inst, target, source, width=32): source_is_register = isinstance(source, Register) if target is eax and (not source_is_register): if isinstance(source, int): inst.chr(0x3d) inst.pack('i', source) else: raise AssemblyError('unsupported source operand: %s' % source) elif isinstance(target, Register): if source_is_register: inst.chr(0x39) inst.modrm(3, source, target) elif isinstance(source, int): if width == 32: inst.chr(0x81) inst.modrm(3, 7, target) inst.pack('i', source) elif width == 8: inst.chr(0x80) inst.modrm(3, 7, target) inst.chr(source) else: raise AssemblyError('unsupported source operand: %s' % source) elif isinstance(target, Address): if source_is_register: raise AssemblyError('unsupported source operand: %s' % target) elif isinstance(source, int): if width == 32: inst.chr(0x81) elif width == 8: inst.chr(0x80) inst.modrmoff(7, target, target.offset) if width == 32: inst.pack('i', source) elif width == 8: inst.pack('b', source) else: raise AssemblyError('unsupported source operand: %s' % target) else: raise AssemblyError('unsupported target operand: %s' % target)
def _impl(inst, operand): if isinstance(operand, Address): inst.chr(0xd9) inst.modrmoff(modrm_target, operand, operand.offset) elif isinstance(operand, st): inst.chr(st1) inst.chr(st2 + operand.index) else: raise AssemblyError('unsupported operand: %s: %s' % (name, operand))
def _impl(inst, operand=None): if operand: if isinstance(operand, st): inst.chr(0xde) inst.chr(opcode + operand.index) else: raise AssemblyError('unsupported operand: %s: %s' % (name, operand)) else: inst.chr(0xde) inst.chr(opcode + 1)
def push(inst, value): if isinstance(value, Register): inst.chr(0x50 + value.index) elif isinstance(value, int): inst.chr(0x68) inst.pack('i', value) elif isinstance(value, float): inst.chr(0x68) inst.pack('f', value) else: raise AssemblyError('unsupported push argument: %s' % value)
def _impl(inst, target, source=None): if source: if isinstance(target, st) and isinstance(source, st): if target.index == 0: inst.chr(0xd8) inst.chr(st0_target + source.index) elif source.index == 0: inst.chr(0xdc) inst.chr(st0_source + target.index) else: raise AssemblyError( '%s with registers must involve st(0)' % name) else: raise AssemblyError('unsupported operands: %s: %s %s' % (name, target, source)) else: operand = target if isinstance(operand, Address): inst.chr(0xd8) inst.modrmoff(modrm_target, operand, operand.offset) else: raise AssemblyError('unsupported operand: %s: %s' % (name, operand))
def dec(inst, operand, width=32): if isinstance(operand, Register): if isinstance(operand, QWordRegister): inst.chr(0x48) inst.chr(0xff) inst.chr(0xc8 + operand.index) elif isinstance(operand, Address): if width == 8: inst.chr(0xfe) elif width == 32: inst.chr(0xff) inst.modrmoff(1, operand, operand.offset) else: raise AssemblyError('dec not implemented for non registers')
def fcmovb(inst, register): if isinstance(register, st): inst.chr(0xda) inst.chr(0xc0 + register.index) else: raise AssemblyError('unsupported operand: fcmovbe: %s' % register)
def fcomi(inst, operand): if isinstance(operand, st): inst.chr(0xdb) inst.chr(0xf0 + operand.index) else: raise AssemblyError('unsupported operand: %s' % operand)
def pop(inst, value): if isinstance(value, Register): inst.chr(0x58 + value.index) else: raise AssemblyError('unsupported pop argument: %s' % value)
def call(inst, offset, operand): if isinstance(operand, Register): inst.chr(0xff) inst.modrm(3, 2, operand) else: raise AssemblyError('unsupported operand: %s' % operand)
def mov(inst, target, source, width=32): source_is_addr = isinstance(source, Address) target_is_addr = isinstance(target, Address) if isinstance(target, QWordRegister) or isinstance(source, QWordRegister): #probably not correct as the REX byte is more complex inst.chr(0x48) if source_is_addr and target_is_addr: raise AssemblyError('cannot transfer address to address') if source_is_addr or target_is_addr: post = lambda: None if source_is_addr: if isinstance(target, ByteRegister): opcode = 0x8a elif isinstance(target, DWordRegister): opcode = 0x8b offset = source.offset arg1, arg2 = target, source elif target_is_addr: if isinstance(source, ByteRegister): opcode = 0x88 elif isinstance(source, DWordRegister): opcode = 0x89 elif isinstance(source, int): value = source source = 0 if width == 32: opcode = 0xc7 post = lambda: inst.pack('i', value) elif width == 8: opcode = 0xc6 post = lambda: inst.chr(value) offset = target.offset arg1, arg2 = source, target inst.chr(opcode) inst.modrmoff(arg1, arg2, offset) post() else: ## in py3 int represents long? # if isinstance(source, int): # if isinstance(target, ByteRegister): # inst.chr(0xb0 + target.index) # inst.chr(source) # if isinstance(target, DWordRegister): # inst.chr(0xb8 + target.index) # inst.pack('i', source) # elif isinstance(source, long): if isinstance(source, int): inst.chr(0xb8 + target.index) inst.pack('I', source) elif isinstance(source, Register): if isinstance(source, ByteRegister): inst.chr(0x88) elif isinstance(source, DWordRegister): inst.chr(0x89) inst.modrm(3, source, target) elif isinstance(source, Data): inst.chr(0xb8 + target.index) inst.pack('I', source.address) else: raise AssemblyError('incompatible source type: %s' % type(source))