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.)