mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Improve handling of Jmp/Call/Push/Pop
This commit is contained in:
@@ -232,6 +232,10 @@ def test_assembler():
|
||||
|
||||
|
||||
CheckInstr(Pop)('RAX')
|
||||
CheckInstr(Push, must_fail=True)('EAX')
|
||||
CheckInstr(Pop)('R15')
|
||||
CheckInstr(Pop)(mem("[ECX]"))
|
||||
CheckInstr(Pop)(mem("[RCX]"))
|
||||
assert len(Pop("RAX").get_code()) == 1
|
||||
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ class X64(object):
|
||||
@staticmethod
|
||||
def is_reg(name):
|
||||
try:
|
||||
return (name.upper() in reg_order) or X64.is_new_reg(name) or X64.is_32b_reg(name)
|
||||
return X64.is_64b_reg(name) or X64.is_32b_reg(name)
|
||||
except AttributeError: # Not a string
|
||||
return False
|
||||
|
||||
@@ -164,6 +164,13 @@ class X64(object):
|
||||
except AttributeError: # Not a string
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def is_64b_reg(name):
|
||||
try:
|
||||
return (name.upper() in x64_regs)
|
||||
except AttributeError: # Not a string
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def is_32b_reg(name):
|
||||
try:
|
||||
@@ -656,6 +663,38 @@ class ModRM_REG__REG(SubModRM):
|
||||
self.setup_rm_as_register(arg1)
|
||||
self.direction = 0
|
||||
|
||||
class ModRM_REG64__REG64(SubModRM):
|
||||
"""handle Reg64 Only, used by slash(x) that do not allow 32bits/rex (push / call / jmp)"""
|
||||
@classmethod
|
||||
def match(cls, arg1, arg2):
|
||||
return X64.is_64b_reg(arg1) and X64.is_64b_reg(arg2)
|
||||
|
||||
def setup_reg_as_register(self, name):
|
||||
name = name.upper()
|
||||
# register IS a 64b register
|
||||
self.setup_as_64bit_operation()
|
||||
self.reg = X64RegisterSelector.get_reg_bits(name)
|
||||
if X64.is_new_reg(name):
|
||||
self.is_rex_needed = True
|
||||
self.rex[5] = 1
|
||||
|
||||
def setup_rm_as_register(self, name):
|
||||
name = name.upper()
|
||||
# register IS a 64b register
|
||||
self.setup_as_64bit_operation()
|
||||
|
||||
self.rm = X64RegisterSelector.get_reg_bits(name)
|
||||
if X64.is_new_reg(name):
|
||||
self.is_rex_needed = True
|
||||
self.rex[7] = 1
|
||||
|
||||
def __init__(self, arg1, arg2, reversed, instr_state):
|
||||
super(ModRM_REG64__REG64, self).__init__()
|
||||
|
||||
self.mod = BitArray(2, "11")
|
||||
self.setup_reg_as_register(arg2)
|
||||
self.setup_rm_as_register(arg1)
|
||||
self.direction = 0
|
||||
|
||||
class ModRM_REG64__MEM(SubModRM):
|
||||
@classmethod
|
||||
@@ -772,10 +811,13 @@ class REG64__MEM_Slash(ModRM_REG64__MEM):
|
||||
class Slash(object):
|
||||
"No idea for the name: represent the modRM for single args + encoding in reg (/7 in cmp in man intel)"
|
||||
|
||||
def __init__(self, reg_num):
|
||||
# only64b seems to be the contrary ok Instr.default_32_bits use this as a base ?
|
||||
# Make a Slash64 () ?
|
||||
def __init__(self, reg_num, only64b=False):
|
||||
"reg = 7 for /7"
|
||||
self.reg = reg_order[reg_num]
|
||||
self.reg_num = reg_num
|
||||
self.only64b = only64b
|
||||
|
||||
def accept_arg(self, args, instr_state):
|
||||
if len(args) < 1:
|
||||
@@ -785,8 +827,13 @@ class Slash(object):
|
||||
injected_reg = self.reg
|
||||
if X64.is_32b_reg(args[0]):
|
||||
injected_reg = registers_64_to_32_bits[injected_reg]
|
||||
if self.only64b:
|
||||
modrm_reg_reg_type = ModRM_REG64__REG64
|
||||
else:
|
||||
modrm_reg_reg_type = ModRM_REG__REG
|
||||
|
||||
try:
|
||||
arg_consum, value, rex = ModRM([ModRM_REG__REG, REG64__MEM_Slash], has_direction_bit=False).accept_arg(args[:1] + [injected_reg] + args[1:], instr_state)
|
||||
arg_consum, value, rex = ModRM([modrm_reg_reg_type, REG64__MEM_Slash], has_direction_bit=False).accept_arg(args[:1] + [injected_reg] + args[1:], instr_state)
|
||||
except ValueError as e:
|
||||
# Size mismatch
|
||||
return None, None, None
|
||||
@@ -868,11 +915,14 @@ class JmpType(Instruction):
|
||||
class Push(Instruction):
|
||||
encoding = [(RawBits.from_int(5, 0x50 >> 3), X64RegisterSelector()),
|
||||
(RawBits.from_int(8, 0x68), AnyImm32()),
|
||||
(RawBits.from_int(8, 0xff), Slash(6))]
|
||||
(RawBits.from_int(8, 0xff), Slash(6, only64b=True))]
|
||||
|
||||
|
||||
class Pop(Instruction):
|
||||
encoding = [(RawBits.from_int(5, 0x58 >> 3), X64RegisterSelector())]
|
||||
encoding = [(RawBits.from_int(5, 0x58 >> 3), X64RegisterSelector()),
|
||||
(RawBits.from_int(8, 0x8f), Slash(0, only64b=True))
|
||||
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -976,12 +1026,13 @@ class JmpImm32(JmpImm):
|
||||
|
||||
class Call(JmpType):
|
||||
encoding = [(RawBits.from_int(8, 0xe8), JmpImm32(5)),
|
||||
(RawBits.from_int(8, 0xff), Slash(2))]
|
||||
(RawBits.from_int(8, 0xff), Slash(2, only64b=True))]
|
||||
|
||||
|
||||
class Jmp(JmpType):
|
||||
encoding = [(RawBits.from_int(8, 0xeb), JmpImm8(2)),
|
||||
(RawBits.from_int(8, 0xe9), JmpImm32(5)),
|
||||
(RawBits.from_int(8, 0xff), Slash(4, only64b=True)),
|
||||
(RawBits.from_int(13, 0xffe0 >> 3), X64RegisterSelector())]
|
||||
|
||||
|
||||
|
||||
@@ -698,7 +698,6 @@ class JmpImm8(JmpImm):
|
||||
class JmpImm32(JmpImm):
|
||||
accept_as_Ximmediat = staticmethod(accept_as_32immediat)
|
||||
|
||||
|
||||
# Instructions
|
||||
|
||||
class Call(JmpType):
|
||||
@@ -709,6 +708,7 @@ class Call(JmpType):
|
||||
class Jmp(JmpType):
|
||||
encoding = [(RawBits.from_int(8, 0xeb), JmpImm8(2)),
|
||||
(RawBits.from_int(8, 0xe9), JmpImm32(5)),
|
||||
(RawBits.from_int(8, 0xff), Slash(4)),
|
||||
(RawBits.from_int(8, 0xea), SegmentSelectorAbsoluteAddr())]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user