#include <stdio.h>
#include <math.h>
int main(int argc, const char *argv[])
{
long i, max;
long sum = 0;
max = (long)pow(2,32);
for (i = 0; i < max; i++) {
sum += i;
}
printf("%ld\n", sum);
return 0;
}
$gcc -S main.c
问题是:在下面的.L2
代码中,-8(%rbp)
总是等于0,而%rax
是总是大于零。所以这是一个无限循环?如果我用gcc -S -O1 main.c
编译,就很清楚了。我真的很苦恼!
汇编代码的一小部分:
main:
pushq %rbp
movq %rsp, %rbp
subq $48, %rsp
movl %edi, -36(%rbp)
movq %rsi, -48(%rbp)
movq $0, -16(%rbp)
movl $0, -8(%rbp)
movl $2, -4(%rbp)
movq $0, -24(%rbp)
jmp .L2
.L3:
movq -24(%rbp), %rax
addq %rax, -16(%rbp)
addq $1, -24(%rbp)
.L2:
movq -24(%rbp), %rax
cmpq -8(%rbp), %rax
jl .L3
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
最佳答案
真正的循环计数器 (i
) 在 -24(%rbp)
。在第三行,它增加了。在第 4 行,它被加载到 rax
中。所以 rax
不是常量零,它与 i
一起遍历值。
-8(%rbp)
是 max
所在的位置。因此,将 i
的值与其进行比较,这就是您的循环退出条件。 -8(%rbp)
不应为零。如果是,我闻到了流氓 32 位算法的味道。
编辑:我想我知道是怎么回事了。常量 2 和 32 是 int
,而不是 long
,因此假定为 32 位。 int
的大小取决于平台;甚至 GCC 的惯例也可能有所不同。 pow(int, int)
被实现为内在的。当参数为 32 位时,2^32 为 0。
替换
max = (long)pow(2,32);
与
max = pow(2l, 32l);
或者用一个常数更好:
max = 0x100000000l;
正如我和其他人所怀疑的那样,混合中有一 block 32 位。
关于c++ - x86-64 汇编程序中的无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19842609/