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
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.

| improve this answer | |
  • 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 6 '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 6 '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 6 '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 7 '14 at 3:18

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.