x86 assembly abs() implementation?

This is how the C library function abs() does it in assembly without branching:

   abs(x) = (x XOR y) - y

where y = x >> 31 (assuming 32-bit input), and >> is arithmetic right shift operator.

Explanation of the above formula:
We want to generate 2’s complement of negative x only.

y = 0xFFFFFFFF, if x is negative
    0x00000000, if x is positive

So when x is positive x XOR 0x00000000 is equal to x . And when x is negative x XOR 0xFFFFFFFF is equal to 1’s complement of x. Now we just need to add 1 to get its 2’s complement which is what expression -y is doing . Because 0xFFFFFFFF is -1 in decimal.

Let’s look at assembly generated for following code by gcc (4.6.3 on my machine):

C code:

main()
{
  int x;
  int output = abs(x);
}

gcc 4.6.3 generated assembly snippet (AT&T syntax), with my comments:

  movl  -8(%rbp), %eax    # -8(%rbp) is memory for x on stack
  sarl  $31, %eax         #  shift arithmetic right: x >> 31, eax now represents y
  movl  %eax, %edx        #  
  xorl  -8(%rbp), %edx    #  %edx = x XOR y
  movl  %edx, -4(%rbp)    # -4(%rbp) is memory for output on stack
  subl  %eax, -4(%rbp)    # (x XOR y) - y

BONUS (from Hacker’s Delight): If you have a fast multiply by +1 and -1, the following will give you abs(x) for 32-bit x:

      ((x >> 30) | 1) * x

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)