assemblyx86reverse-engineeringsseimmediate-operand

Replace `movss xmm0, cs:dword_5B27420` with `movss xmm0, immediate`


I have a linux .so file in Ida Pro and I have the following instruction:

movss   xmm0, cs:dword_5B27420

Is it possible to move a fixed value into xmm0 using the same or less number of bytes than that instruction?

The instruction bytes are:

F3 0F 10 05 C8 BB A 00

I want to do something like:

movss   xmm0, 0.3

Solution

  • Not in fewer bytes; if you don't have room here, you'd have to jump somewhere else and then back, or just change the RIP-relative address to load a different constant from somewhere else. (e.g. from padding between two functions, or spare space in .rodata or .data if there is any.)

    There is no mov-immediate to XMM registers, and mov eax, __?float32?__(0.3) (5 bytes) / movd xmm0, eax (4 bytes) would take more total bytes. (That's NASM syntax for the integer value that is the bit-pattern for the given FP constant. Some assemblers may allow mov eax, 0.3, in case that's ever useful.)

    Ways other than immediates to construct FP constants include pcmpeqd xmm0,xmm0 (4 bytes) and then shifting or doing other things (like pabsd) with the all-ones bit patterns. But that's at least 2 instructions unless you want a NaN. (See Agner Fog's optimizing asm guide, and What are the best instruction sequences to generate vector constants on the fly?)

    0.3f is not a simple constant you could materialize even in 3 instructions from 0xffffffff with left and right shifts, unlike 1.0f for example. (But that's still three instructions, 4 and 5 bytes each to construct set1(1.0f))

    cmpps is SSE1 non-scalar so it has a smaller opcode than pcmpeqd (no mandatory prefixes, just 0f c2), but isn't any smaller overall because it needs an immediate for the compare predicate.