diff --git a/native_exec/simple_x64.py b/native_exec/simple_x64.py index c1e5df2..67ec4a6 100644 --- a/native_exec/simple_x64.py +++ b/native_exec/simple_x64.py @@ -574,6 +574,11 @@ class Pop(Instruction): class Call(Instruction): encoding = [(RawBits.from_int(8, 0xff), Slash(2))] +class Xchg(Instruction): + default_32_bits = True + encoding = [(RawBits.from_int(5, 0x90 >> 3), RegisterRax(), X64RegisterSelector()), + (RawBits.from_int(5, 0x90 >> 3), X64RegisterSelector(), RegisterRax())] + class Ret(Instruction): encoding = [(RawBits.from_int(8, 0xc3),)] diff --git a/native_exec/simple_x86.py b/native_exec/simple_x86.py index e6b8b69..ac3d26f 100644 --- a/native_exec/simple_x86.py +++ b/native_exec/simple_x86.py @@ -381,7 +381,7 @@ class Slash(object): raise ValueError("Missing arg for Slash") # Reuse all the MODRm logique with the reg as our self.reg # The sens of param is strange I need to fix the `reversed` logique - arg_consum, value = ModRM([ModRM_REG__REG, ModRM_REG__MEM]).accept_arg(previous, args[:1] + [self.reg] + args[1:]) + arg_consum, value = ModRM([ModRM_REG__REG, ModRM_REG__MEM], has_direction_bit=False).accept_arg(previous, args[:1] + [self.reg] + args[1:]) if value is None: return arg_consum, value return arg_consum-1, value @@ -451,9 +451,6 @@ class Mov(Instruction): class Lea(Instruction): encoding = [(RawBits.from_int(8, 0x8d), ModRM([ModRM_REG__MEM], accept_reverse=False, has_direction_bit=False))] -class Call(Instruction): - encoding = [(RawBits.from_int(13, 0xffd0 >> 3), X86RegisterSelector())] - class Cmp(Instruction): encoding = [(RawBits.from_int(8, 0x3d), RegisterEax(), Imm32()), (RawBits.from_int(8, 0x81), Slash(7), Imm32()), @@ -508,6 +505,12 @@ class Jnz(JmpType): class Xor(Instruction): encoding = [(RawBits.from_int(8, 0x31), ModRM([ModRM_REG__REG]))] +class Xchg(Instruction): + encoding = [(RawBits.from_int(5, 0x90 >> 3), RegisterEax(), X86RegisterSelector()), (RawBits.from_int(5, 0x90 >> 3), X86RegisterSelector(), RegisterEax())] + +class Call(Instruction): + encoding = [(RawBits.from_int(8, 0xff), Slash(2))] + class Ret(Instruction): encoding = [(RawBits.from_int(8, 0xc3),)] diff --git a/native_exec/test_simple_x64.py b/native_exec/test_simple_x64.py index 8e9f046..209b57c 100644 --- a/native_exec/test_simple_x64.py +++ b/native_exec/test_simple_x64.py @@ -95,4 +95,7 @@ TestInstr(Push)('R15') TestInstr(Push)(0x42) TestInstr(Push)(-1) TestInstr(Call)('RAX') -TestInstr(Call)(mem('[RAX + RCX * 8]')) \ No newline at end of file +TestInstr(Call)(mem('[RAX + RCX * 8]')) + +TestInstr(Xchg)('RAX', 'RSP') +assert Xchg('RAX', 'RCX').get_code() == Xchg('RCX', 'RAX').get_code() \ No newline at end of file diff --git a/native_exec/test_simple_x86.py b/native_exec/test_simple_x86.py index 4a9d5d7..8d61fa1 100644 --- a/native_exec/test_simple_x86.py +++ b/native_exec/test_simple_x86.py @@ -80,3 +80,8 @@ TestInstr(Add)('EAX', 0xffffffff) TestInstr(Lea)('EAX', mem('[EAX + 1]')) TestInstr(Lea)('ECX', mem('[EDI + -0xff]')) +TestInstr(Call)('EAX') +TestInstr(Call)(mem('[EAX + ECX * 8]')) + +TestInstr(Xchg)('EAX', 'ESP') +assert Xchg('EAX', 'ECX').get_code() == Xchg('ECX', 'EAX').get_code()