assembly - x86汇编abs()实现?

标签 assembly x86

我需要得到2个有符号整数的差。 x86汇编语言中是否有ABS()函数,所以我可以这样做。任何帮助将不胜感激。

最佳答案

这是C库函数abs()在汇编中不分支的方式:

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

其中y = x >>> 31(假定为32位输入),而>>>是算术右移运算符。

上述公式的解释:
我们只想生成负x的2的补码。
y = 0xFFFF, if x is negative
    0x0000, if x is positive

因此,当x为正时x XOR 0x0000等于x。当x为负数时,x XOR 0xFFFF等于x的1的补码。现在我们只需要添加1即可得到其2的补码,这就是-y表达式的作用。因为0xFFFF为十进制-1。

让我们看一下gcc(在我的机器上为4.6.3)为以下代码生成的程序集:

C代码:
main()
{
  int x;
  int output = abs(x);
}

gcc 4.6.3生成了程序集摘要(AT&T语法),并附有我的评论:
  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

奖励(来自Hacker's Delight):如果您将+1和-1快速相乘,则以下内容将为您提供abs(x):
      ((x >>> 30) | 1) * x

关于assembly - x86汇编abs()实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2639173/

相关文章:

linux - 为什么 strace 报告我的 x64 FASM 程序在 32 位模式下运行?

c - 如何在ARMv6+上实现16bit立体声混音?

在 Unix 系统上使用时,Python Ctypes 函数调用段错误

assembly - GNU gas 中的 .zero 是什么?

c - 了解 Aleph One 的第一个缓冲区溢出漏洞

assembly - 如何使用汇编写入标准输出?

assembly - 程序调用如何在汇编程序中工作?

assembly - 为什么所有现代 x86 掩码都会将计数移至 CL 中的 5 个低位

linux - 如何使用 BSS var 将字符串移动到寄存器 NASM

c++ - 为什么 MSVC 在执行此位测试之前会发出无用的 MOVSX?