Reverse Engineering for Beginners

(avery) #1

CHAPTER 45. BRANCHLESS ABS() FUNCTION CHAPTER 45. BRANCHLESS ABS() FUNCTION


Chapter 45


Branchless abs() function


Let’s revisit an example we considered earlier12.2 on page 131and ask ourselves, is it possible to make a branchless version
of the function in x86 code?


int my_abs (int i)
{
if (i<0)
return -i;
else
return i;
};


And the answer is yes.


45.1 Optimizing GCC 4.9.1 x64


We could see it if we compile it using optimizing GCC 4.9:


Listing 45.1: Optimizing GCC 4.9 x64

my_abs:
mov edx, edi
mov eax, edi
sar edx, 31
; EDX is 0xFFFFFFFF here if sign of input value is minus
; EDX is 0 if sign of input value is plus (including 0)
; the following two instructions have effect only if EDX is 0xFFFFFFFF
; or idle if EDX is 0
xor eax, edx
sub eax, edx
ret


This is how it works:


Arithmetically shift the input value left by 31. Arithmetical shift implies sign extension, so if theMSBis 1, all 32 bits are to
be filled with 1, or with 0 if otherwise. In other words, theSAR REG, 31instruction makes0xFFFFFFFFif the sign was
negative or 0 if positive. After the execution ofSAR, we have this value inEDX. Then, if the value is0xFFFFFFFF(i.e., the
sign is negative), the input value is inverted (becauseXOR REG, 0xFFFFFFFFis effectively an inverse all bits operation).
Then, again, if the value is0xFFFFFFFF(i.e., the sign is negative), 1 is added to the final result (because subtracting− 1
from some value resulting in incrementing it). Inversion of all bits and incrementing is exactly how two’s complement value
is negated:30 on page 431.


We may observe that the last two instruction do something if the sign of the input value is negative. Otherwise (if the sign
is positive) they do nothing at all, leaving the input value untouched.


The algorithm is explained in [War02, pp. 2-4]. It’s hard to say, how GCC did it, deduced it by itself or found a suitable pattern
among known ones?

Free download pdf