我是集会上的一个总菜鸟,只是捅了一下,看看发生了什么。无论如何,我写了一个非常简单的函数:
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
之外,汇编输出对我(大部分)都有意义。通过谷歌搜索,我认为这样做的目的只是将%eax
设置为零,在这种情况下对应于我的迭代器long i;
。
但是,除非我弄错了,%eax
是32位寄存器。所以在我看来这实际上应该是xorq %rax, %rax
,特别是因为它持有一个64位长的int。此外,在代码的下游,它实际上使用64位寄存器%rax
来进行迭代,它永远不会在xorl %eax %eax
之外进行初始化,这似乎只会将低32位的值归零。登记册。
我错过了什么吗?
另外,出于好奇,为什么底部有两个.long
常数?第一个858993459
等于2.4
的双浮点表示,但我无法弄清楚第二个数字是什么或为什么存在。
答案 0 :(得分:9)
我认为这样做的目的只是将%eax设置为零
是
在这种情况下对应于我的迭代器long i;。
没有。您的i
在声明中未初始化。严格地说,该操作对应于for循环中的i = 0
表达式。
但是,除非我弄错了,%eax是一个32位寄存器。所以在我看来,这实际上应该是xorq%rax,%rax,特别是因为它持有一个64位长的int。
但清除寄存器的低位双字会清除整个寄存器。这不直观,但它含蓄。
答案 1 :(得分:2)
回答第二部分:.long
表示32位,两个积分常数并排形成双2.4的IEEE-754表示形式:
Dec: 1073951539 858993459
Hex: 0x40033333 0x33333333
400 3333333333333
S+E Mantissa
指数偏移1023,因此实际指数为0x400 - 1023 = 1.尾数中的前导“一”是隐含的,因此它是2 1 ×0b1.001100110011 ... (您认为这个周期性扩展为3/15,即0.2。果然,2×1.2 = 2.4。)