#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)
始终等于零,%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"
答案 0 :(得分:2)
真实循环计数器(i
)位于-24(%rbp)
。在第三行,它增加了。在第4行,它被加载到rax
。因此rax
不是常数零,它与i
一起贯穿值。
-8(%rbp)
,假设是max
。所以将i
的值与之进行比较,这就是你的循环退出条件。 -8(%rbp)
不应为零。如果是,我闻到流氓32位算术。
int
,而不是long
,因此假定为32位。 int
的大小取决于平台;甚至海湾合作委员会的公约也许会有所不pow(int, int)
被实现为内在的。参数为32位时,2 ^ 32为0。
替换
max = (long)pow(2,32);
带
max = pow(2l, 32l);
或者使用常数更好:
max = 0x100000000l;
就像我和其他人所怀疑的那样,混合中有一块32位。
答案 1 :(得分:1)
不,它不是无限循环。首先,%rax并不总是大于0,在该行中它从-24(%rbp)获得值,这显然是变量i
。当它进入循环时,它将-24(%rbp)设置为零,然后跳转到.L2它发生在您未显示的部分。如果-{(%rbp)是变量max
的值等于零(在溢出的情况下)jl
将不会跳转到.L3并且循环将在首次检查后终止。
我不太明白为什么你需要为此阅读汇编,这在C ++源代码中非常明显。