簡體   English   中英

x86-64匯編程序中的無限循環

[英]An infinite loop in x86-64 assembler

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

實循環計數器( i )在-24(%rbp) 第三行,它增加了。 在第四行,將其加載到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;

就像我和其他人所懷疑的那樣,其中包含32位。

不,這不是無限循環。 首先%rax並不總是大於0,在那一行它從-24(%rbp)中獲取值,這顯然是變量i 當它進入循環時,會將-24(%rbp)設置為零,然后跳轉到.L2。這部分發生在您未顯示的位置。 如果-8(%rbp)(即max的變量的max )等於零(在發生溢出的情況下), jl將不會跳轉到.L3,並且循環將在第一次檢查后終止。 我不太明白為什么需要為此閱讀匯編語言,這在C ++源代碼中很明顯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM