【发布时间】:2013-11-07 17:27:50
【问题描述】:
#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"
【问题讨论】:
-
long的大小是多少?如果它是 32 位(4 字节),那么pow(2, 32)将溢出。如果您想要long的最大值,那么您应该在 C++ 中使用std::numeric_limits,并在 C 中使用<limits.h>头文件中的LONG_MAX。 -
-8(%rbp)是max的值,因此它显然不应该为零。也许你可以展示更多它被设置的汇编器。 -
当您检查它是否为零时,您从 -8(%rbp) 读取了多少字节?它的值应该是
0x100000000,它的低 32 位为零。 -
@JoachimPileborg Pileborg 很抱歉没有明确说明,我使用 ubuntu 12.04 x86_64。所以
long的大小是8字节,那么pow(2,32)就不会溢出了。 -
@mbratch 但
-8(%rbp)被初始化为零。cmpq -8(%rbx), %rax的第一次是真的,然后总是真的。