8

When I decompile using IDA PRO I get code which could look like both of these

Understanding the __PAIR__ macro.

Macro itself.

// The following definition is not quite correct because it always returns
// uint64. The above C++ functions are good, though.
#define __PAIR__(high, low) (((unsigned long)(high)<<sizeof(high)*8) | low)

if ( (__PAIR__(a4, a3) & 0x8000000000000000ui64) == 0i64 ) {
  //condition code.
}

I also have code that looks like this

  if ( (__PAIR__(v17, v12) & 0x8000000000000000ui64) != 0i64 ) {
    //condition code.
  }

I actually found some guy who helped me repair this bad looking code and as far I could tell by the pattern they could simply be replaced like so.

   if( (__PAIR__(a4, a3) & 0x8000000000000000ui64) == 0i64 )

becomes

   if(a4 >= 0 && a3 >= 0)

Now I found a very similar pattern that looks like above but instead of == 0i64 it has != 0i64

So I figured if my pattern is correct then the following code below

  if ( (__PAIR__(v17, v12) & 0x8000000000000000ui64) != 0i64 ) {

should look like this

  if( v17 < 0 || v12 < 0 ) {

Then again that's just a guess I wonder if that's correct.

I can't post the assembly for the != 0i64 example as I couldn't find it the assembly code is very big.. but the one with == 0i64 looks like this

.text:004049F0                 mov     edx, [esp+a3]
.text:004049F4                 test    edx, edx
.text:004049F6                 jl      short locret_404A3E
.text:004049F8                 mov     eax, [esp+a4]
.text:004049FC                 test    eax, eax
.text:004049FE                 jl      short locret_404A3E
user3435580
  • 243
  • 2
  • 8

1 Answers1

4
 if( (__PAIR__(a4, a3) & 0x8000000000000000ui64) == 0i64 )

becomes

 if(a4 >= 0 && a3 >= 0)

No, that's not correct. The correct simplification is:

if ((int)a4 >= 0)
 if ( (__PAIR__(v17, v12) & 0x8000000000000000ui64) != 0i64 ) {

should look like this

 if( v17 < 0 || v12 < 0 ) {

Nope, it should look like this:

if ((int)v17 < 0) {

You may want to read up on how the most significant bit (MSB) is used as the sign bit in two's complement notation.

Jason Geffner
  • 20,681
  • 1
  • 36
  • 75
  • But it seems to be a PAIR of 2 variables why only one is used there? I understand the variables could be created out of thin-air due to the way assembly works. But I do believe this should still check both at once am I wrong? also since it checks for a 64 bit mask i'm guessing thats 32 bit per variable? this is made for x86 exe not 64bit exe. – user3435580 May 06 '14 at 19:47
  • It appears in the disassembly as two variables because the original code used a 64-bit variable, which gets broken up into two 32-bit variables in the disassembly. Since only the MSB of the 64-bit value is checked (since the code is checking the value's sign), the lower DWORD portion of the 64-bit value is irrelevant, which is why my simplified code above ignores a3 and v12. – Jason Geffner May 06 '14 at 21:44
  • So as far as I understand IDA PRO did a bad analyze on the assembly to think it's 64bit when it's really 2 variables DWORDS. Why does the assembly above I posted have a3 and a4 I think the asm is interpreted the same in ollydebugger as well that assembly is for the == 0i64 – user3435580 May 06 '14 at 23:53
  • "IDA PRO did a bad analyze on the assembly to think it's 64bit when it's really 2 variables DWORDS" -- no, it really is a 64 bit value; IDA didn't make a mistake here as far as I can see. – Jason Geffner May 07 '14 at 03:18