Xorl% eax,% eax в x86_64 код сборки, созданный gcc

Я нахожусь в полной нобе на собрании, просто немного заглядывая, чтобы понять, что происходит. Во всяком случае, я написал очень простую функцию:

void multA(double *x,long size)
{
  long i;
  for(i=0; i<size; ++i){
    x[i] = 2.4*x[i];
  }
}

Я скомпилировал его с помощью

gcc -S -m64 -O2 fun.c

И я получаю это:

    .file   "fun.c"
    .text
    .p2align 4,,15
    .globl  multA
    .type   multA, @function
multA:
.LFB34:
    .cfi_startproc
    testq   %rsi, %rsi
    jle .L1
    movsd   .LC0(%rip), %xmm1
    xorl    %eax, %eax
    .p2align 4,,10
    .p2align 3
.L3:
    movsd   (%rdi,%rax,8), %xmm0
    mulsd   %xmm1, %xmm0
    movsd   %xmm0, (%rdi,%rax,8)
    addq    $1, %rax
    cmpq    %rsi, %rax
    jne .L3
.L1:
    rep
    ret
    .cfi_endproc
.LFE34:
    .size   multA, .-multA
    .section    .rodata.cst8,"aM",@progbits,8
    .align 8
.LC0:
    .long   858993459
    .long   1073951539
    .ident  "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
    .section    .note.GNU-stack,"",@progbits

Выход сборки имеет смысл для меня (в основном), за исключением строки xorl %eax, %eax. Из googling я понимаю, что целью этого является просто установить %eax в ноль, что в этом случае соответствует моему итератору long i;.

Однако, если я не ошибаюсь, %eax - это 32-разрядный регистр. Поэтому мне кажется, что на самом деле это должно быть xorq %rax, %rax, особенно потому, что это поддерживает 64-битный длинный int. Более того, далее в коде он фактически использует 64-разрядный регистр %rax для выполнения итерации, который никогда не инициализируется вне xorl %eax %eax, который, по-видимому, только обнуляет нижние 32 бита регистра.

Я что-то пропустил?

Кроме того, из любопытства, почему существуют две константы .long внизу? Первый, 858993459 равен двойному плавному представлению 2.4, но я не могу понять, что такое второе число или почему оно есть.

Ответ 1

Я понимаю, что целью этого является просто установить% eax на нуль

Да.

который в этом случае соответствует моему итератору long i;.

Нет. Ваш i не декларируется в объявлении. Строго говоря, эта операция соответствует выражению i = 0 в цикле for.

Однако, если я не ошибаюсь,% eax - это 32-разрядный регистр. Таким образом, мне кажется, что на самом деле это xorq% rax,% rax, особенно потому, что это поддерживает 64-битный длинный int.

Но очистка нижнего двойного слова регистра очищает весь регистр. Это неинтуитивно, но неявно.

Ответ 2

Просто чтобы ответить на вторую часть: .long означает 32 бит, а две интегральные константы бок о бок образуют представление IEEE-754 двойного 2.4:

Dec: 1073951539  858993459
Hex: 0x40033333 0x33333333

     400 3333333333333
     S+E Mantissa

Показатель смещен на 1023, поэтому фактический показатель равен 0x400   1023 = 1. Подразумевается ведущий "один" в мантиссе, поэтому 2 1 & times; 0b1.001100110011... (Вы узнаете это периодическое расширение как 3/15, то есть 0,2., 2 & times; 1,2 = 2.4.)