Improve handling of Jmp/Call/Push/Pop

This commit is contained in:
hakril
2024-06-27 14:22:40 +02:00
parent 006dce7054
commit 53554f45ab
3 changed files with 62 additions and 7 deletions
+4
View File
@@ -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
+57 -6
View File
@@ -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())]
+1 -1
View File
@@ -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())]