keystone-engine / keystone

Keystone assembler framework: Core (Arm, Arm64, Hexagon, Mips, PowerPC, Sparc, SystemZ & X86) + bindings
http://www.keystone-engine.org
GNU General Public License v2.0
2.3k stars 456 forks source link

x86-64 sub/add reg, imm fails with invalid operand when imm > max int32 value #470

Open CallumCVM opened 4 years ago

CallumCVM commented 4 years ago

The sub instruction works when using an immediate value <= the max value of an signed int:

kstool x64 "sub rax, 2147483647" sub rax, 2147483647 = [ 48 2d ff ff ff 7f ]

However, anything greater than this will fail with an invalid operand:

kstool x64 "sub rax, 2147483648" ERROR: failed on ks_asm() with count = 0, error = 'Invalid operand (KS_ERR_ASM_INVALIDOPERAND)' (code = 512)

Myriachan commented 3 years ago

This isn't a bug. The sub instruction on x86-64 can only take a signed 32-bit immediate parameter. 2147483648 is too large for a signed 32-bit value.

If you actually were to encode this (48 2D 00 00 00 80), the processor would interpret it as sub rax, 0xFFFFFFFF80000000: sign-extending the immediate parameter to 64 bits. And Keystone supports sub rax, 0xFFFFFFFF80000000 and sub rax, -2147483648.