简体   繁体   中英

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

The question is: In the .L2 code below, -8(%rbp) always equals zero, and the %rax is always greater than zero. So this is a infinite loop? And if I compile with gcc -S -O1 main.c , it is very clear. I am really troubled!

Just a little part of the assembler code:

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"

The real loop counter ( i ) is at -24(%rbp) . On the third line, it's increased. On the 4th line, it's loaded into rax . So rax is not a constant zero, it runs through values along with i .

-8(%rbp) , one assumes, is where max is. So the value of i is compared to that, and this is your loop exit condition. -8(%rbp) should not be zero. If it is, I smell rogue 32-bit arithmetic.

EDIT: I think I know what's the matter. Constants 2 and 32 are int , not long , therefore assumed to be 32-bit. Size of int is platform dependent; even GCC's convention might vary. pow(int, int) is implemented as as intrinsic. 2^32 is 0 when arguments are 32-bit.

Replace

max = (long)pow(2,32);

with

max = pow(2l, 32l);

Or better with with a constant:

max = 0x100000000l;

Like I and others suspected, there was a piece of 32-bitness in the mix.

No it is not infinite loop. First of all %rax is not always greater than 0, in that line it gets value from -24(%rbp) which is obviously variable i . When it enters the loop it sets -24(%rbp) to zero and then jumps to .L2 It happens in part that you did not show. If -8(%rbp) which is value of variable of max is equal to zero (in case of overflow) jl will not jump to .L3 and loop will terminate after first check. I do not quite understand why you need to read assembly for that, that's pretty obvious from C++ source code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM