chris (fileoffset) <fileoffset fileoffset com> |
Wednesday, January 24 2007 21:52.39 CST |
If trying to get the high dword of an overflow multiply calculation, i.e:
0x0aabbcc * 0x0ddeeff = 0x09403 [edx] 83c4b834 [eax]
Doing something like this in IDC:
auto a = 0x0aabbcc * 0x0ddeeff;
will result in 'a' being the lower dword only (0x083c4b834). A workaround for this is to force one of the operands to a floating point constant like such:
auto a = 11189196.0 * 0x0ddeeff;
'a' is now a floating point number. Attempting to shift it right will fail, since IDA attempts to convert the floating point to a long and fails, so we must do it the long way (divide by 0x0ffffffff):
auto a = (11189196.0 * 0x0ddeeff) / 4294967295.0;
'a' is now 0x09403, just what we wanted :)
If anyone knows a better way to do this, feel free to comment...
Actually shifting 32 bits right is not the same with dividing with 0xFFFF_FFFF. It should be with 0x1_0000_0000.
Anyway, here's a longer but integer-only solution:
static mul64_hi (a, b)
{
auto a0, a1, b0, b1, r0, r1, r01, r23;
a0 = a & 0xFFFF;
a1 = (a >> 0x10) & 0xFFFF;
b0 = b & 0xFFFF;
b1 = (b >> 0x10) & 0xFFFF;
r0 = a0 * b0;
r1 = a1 * b0 + a0 * b1 + ((r0 >> 0x10) & 0xFFFF);
r23 = a1 * b1 + ((r1 >> 0x10) & 0xFFFF);
r01 = (r0 & 0xFFFF) | (r1 << 0x10);
Message("mul64: %08Xh * %08Xh = %08X_%08Xh", a, b, r23, r01);
return (r23);
}
static main ()
{
mul64_hi(0x0AABBCC, 0x0DDEEFF);
}
|
My bad, 0x010000000 it is.
As you say ico, yours is longer but more useful if neither of the sides of the multiplication are constants (or you cannot force either side to type float). However a revised (tested) version:
static mul64_hi(a, b)
{
return (a * 1.0) * (b * 1.0) / 4294967296.0;
}
also seems to work well.
|
|