Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

x86 assembly abs() implementation?

Tags:

x86

assembly

I need to get the difference of 2 signed integers. Is there an ABS() function in x86 assembly language so I can do this. Any help would be greatly appreciated.

like image 677
Greg C. Avatar asked Apr 14 '10 16:04

Greg C.


People also ask

What assembly language is used in x86?

x86 Assembly Guide. There are several different assembly languages for generating x86 machine code. The one we will use in CS216 is the Microsoft Macro Assembler (MASM) assembler. MASM uses the standard Intel syntax for writing x86 assembly code.

How to generate assembly code for 32-bit integer ABS function in C++?

The Microsoft Visual Studio 2005 (C++) generates the following three lines of assembly code for 32-bit integer abs function. cdq xor eax, edx sub eax, edx The above three lines of code removes the branch and is much faster. The cdq copies the sign of the register eax to register edx.

How to insert labels in x86 assembly code?

Labels can be inserted anywhere in x86 assembly code text by entering a label name followed by a colon. For example, The second instruction in this code fragment is labeled begin. Elsewhere in the code, we can refer to the memory location that this instruction is located at in memory using the more convenient symbolic name begin.

How difficult is it to write x86 assembly code in MASM?

MASM uses the standard Intel syntax for writing x86 assembly code. The full x86 instruction set is large and complex (Intel's x86 instruction set manuals comprise over 2900 pages), and we do not cover it all in this guide. For example, there is a 16-bit subset of the x86 instruction set. Using the 16-bit programming model can be quite complex.


2 Answers

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):

      ((x >>> 30) | 1) * x 
like image 156
bits Avatar answered Sep 29 '22 16:09

bits


Old thread but if I surfed in here late you might have too... abs is a brilliant example so this should be here.

; abs(eax), with no branches. ; intel syntax (dest, src)  mov ebx, eax ;store eax in ebx neg eax cmovl eax, ebx ;if eax is now negative, restore its saved value 
like image 30
Hal Avatar answered Sep 29 '22 15:09

Hal