1

I have the following Assembler Code in a x86 Program and I need to modify it as it is buggy:

fld     ds:(flt_203B8 - 29C48h)[ebx]
fdivr   dword ptr [esi+44h]
fmul    ds:(flt_203BC - 29C48h)[ebx]
fisttp  [ebp+var_334]
mov     eax, [ebp+var_334]
cmp     eax, 0Fh
jg      short greater

test    eax, eax
mov     edx, 0
cmovs   eax, edx
jmp     short valueWithinLimits


greater:
mov     eax, 0Fh

valueWithinLimits:
....

In Pseudocode this is

v29 = (signed int)(*(float *)(v3 + 68) / 40.0 * 15.0);
if ( v29 > 15 )
{
  v29 = 15;
}
else if ( v29 < 0 )
{
  v29 = 0;
}

I need to insert the following line as second line:

v29 = 15 - v29;

Is there any way I can do that without needing any more space? I assume no but maybe someone has a smart Idea here what can be done in this case.

2

It's hard to say, since you didn't post the entire assembly related to the pseudocode. It seems however, that the "if" block is implemented via jumps. In that case, you may use conditional moves instead. For example, assuming that "if" block is implemented like this (uses 28 bytes):

  cmp eax, 0Fh
  jg greater
  cmp eax, 0
  jl less
  jmp continue
less:
  mov [ebp+var_334], 0
  jmp continue
greater:
  mov [ebp+var_334], 0Fh
continue:

You may implement it like below:

  mov ebx, 0Fh
  cmp eax, 0Fh
  cmovg eax, ebx
  xor ebx, ebx
  cmp eax, 0
  cmovl eax, ebx
  mov [ebp+var_334], eax

This implementation uses 22 bytes, which is 6 bytes lower than the previous one - exactly the space you need to insert fsubr instruction to compute 15 - st(0) before storing the result in v29.

Consider this implementation:

  xor ebx, ebx    ; ebx = 0
  mov bl, 15      ; ebx = 15
  neg eax         ; eax = -eax
  add eax, ebx    ; eax = 15 - eax
  cmp eax, ebx    
  cmovg eax, ebx
  xor ebx, ebx
  test eax, eax
  cmovs eax, ebx

It's even shorter (occupies 20 bytes), does the whole job and doesn't require additional operations on floats.

  • Correct me if I'm wrong, but in your implementation there is a problem whenever 0<=v29<=15 leading to overwriting v29 with whatever is stored in ecx before your function (undefined behaviour?) – Anonymous Anonymous Apr 2 at 21:28
  • You are right. I’ve edited my answer. – bart1e Apr 3 at 4:52
  • Sorry I didn't notice that I missed part of it, I have completed it now. Seems like I could bring it down to the lower size, however I can not put the 15 anywhere, which makes it impossible to use it I think. I tried to assemble "fsubr 15, %st" but it doesn't work – Roman Apr 3 at 15:57
  • Well, you cannot use immediate values in fsubr (what I wrote was just a shortcut). You can, however, put a constant float equal to 15 if it is present somewhere in your program. If not, let me know and I will suggest you another solution. – bart1e Apr 3 at 16:03
  • It must be present as we are multiplying with 15, however I can't get IDA to assemble with flt_203bc either which is what the fmul uses to multiply with 15 – Roman Apr 3 at 16:07
0

Actually your assembler code isn't complete. It matches to next pseodocode:

v29 = (signed int)(*(float *)(v3 + 68) / 40.0 * 15.0);
if ( v29 > 15 )

0

If 40.0 and 15.0 are constants, you could remove division and only do multiplication with 0.375. Not sure how much space would this save.

0

You have code which scales and offsets, you need to scale and offset. So you do not need to change the code at all, just the constants.

Work your new operation backwards into the existing math. Change the sign of one of the constants you multiply by, and work the offset back through the multiplication and sign change and combine it with the original offset.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.