c - 指令级的有符号数模数

标签 c gcc assembly modulus

阅读 this前段时间关于 gccclangsigned 数模计算的不同实现的有趣讨论向我提出了一个问题(在讨论)。

到底为什么要执行这个:

if(num % 2 == 1)

以此开头(在 clanggcc 中类似):

movl    %edi, %eax
shrl    $31, %eax
addl    %edi, %eax

为什么我们从 ((num >> 31) + num) 开始?为什么取 MSB 并将其添加到号码中?这是从哪里来的?

最佳答案

% 2 的结果是负余数,在 C 中除法向 0 舍入。& 1 仅适用于正数。

因此编译器生成添加符号位数的代码 - 本质上是将负数增加一位,因此 -1 在最后一位中具有 0,然后 -2 在最后一位有 1-3 又有 0 ... 然后我们屏蔽掉除了最后一位,从结果中减去符号位,例如:

movl    %edi, %edx
shrl    $31, %edx
leal    (%rdi,%rdx), %eax
andl    $1, %eax
subl    %edx, %eax

它的性能可能比 idiv 指令稍微好一点。例如,在 Core i7 上,具有 r32 的 IDIV 将具有 17-28 的延迟和 7-12 的吞吐量,而生成的代码中的所有其他代码都具有 ~1

关于c - 指令级的有符号数模数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52933729/

相关文章:

c - 用time.h测量时间?

gcc - GNU make自动删除预编译头

assembly - 学习汇编语言有哪些优点和缺点?

gcc - GNU 汇编标签中美元符号的含义

将 long 转换为字符串,保证不使用堆内存

c++ - C/C++ 编译器警告 : do you clean up all your code to remove them or leave them in?

c - C中语句的最大长度

c++ - ... union 问题中不允许使用构造函数

linux - 指定 GCC 输出二进制文件的预期 Linux 版本

c - 用于图像处理的非常快的 memcpy?