c++ - x86-64 汇编程序中的无限循环

标签 c++ c gcc assembly x86-64

#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/

相关文章:

c++ - Visual Studio C 与 C++ 标志问题

c - libpng,c代码,如何将RGB值转换为像素值?

在一元 & 中转换相关的无效左值

c++ - 网页抓取选项 - 仅限 C++ 版本

c++ - 在没有 stdio 的情况下将数字转换为字符串 C

ios - 如何调试 "watchdog timeout"崩溃日志?

C: 带有 MinGW 的正则表达式库

c++ - 与标准 C++ 相比,C++/CLI(以前称为 "Managed C++")有哪些优势?

c++复制初始化和直接初始化,奇怪的情况

c++ - 如何将模板类容器的迭代器传递给函数?