2015-09-12 167 views
0

因此Im在汇编代码总共小白和阅读他们以及汇编代码的x86

所以当与

gcc -std=c99 -O3 -fno-tree-vectorize -S code.c -o code-O3.s 
编译我有一个简单的C代码

void saxpy() 
{ 
    for(int i = 0; i < ARRAY_SIZE; i++) { 
    float product = a*x[i]; 
    z[i] = product + y[i]; 
} 
} 

和等效汇编代码

给我如下asssembly代码

saxpy: 
.LFB0: 
.cfi_startproc 
movss a(%rip), %xmm1 
xorl %eax, %eax 
.p2align 4,,10 
.p2align 3 
.L3: 
movss x(%rax), %xmm0 
addq $4, %rax 
mulss %xmm1, %xmm0 
addss y-4(%rax), %xmm0 
movss %xmm0, z-4(%rax) 
cmpq $262144, %rax 
jne .L3 
rep ret 
.cfi_endproc 

我也明白,展开循环已经发生 但林不能够理解的意图和想法背后

addq $4, %rax 
mulss %xmm1, %xmm0 
addss y-4(%rax), %xmm0 
movss %xmm0, z-4(%rax) 

有人可以解释,4的使用情况,并 什么呢语句的意思 Y-4 (%rax)

+0

4是浮点大小 –

+0

你能告诉我y-4(%rax)是什么, 假设,我有循环运行20次。优化后的 什么是我的静态和动态insns计数? – svm

+0

另外,需要在Rax寄存器中添加一个立即数4。这是按照声明 “addq $ 4%RAX”做 – svm

回答

1

x,yz是全局数组。您遗漏了符号声明的列表末尾。

put your code on godbolt for you,与所定义的必要全局(和固定缩进)。看看底部。

顺便说一句,有没有展开怎么回事。每个标量单精度mul都有一个,并在循环中添加。试着用-funroll-loops看到它展开。

With -march=haswell, gcc will use an FMA instruction。如果您离开了-fno-tree-vectorize未削弱编译器,以及#define ARRAY_SIZE小,像100,它完全解开与大多32字节FMA指令YMM循环,一些16字节FMA XMM结束。

此外,什么是需要立即值4添加到RAX寄存器。 ,其作为每语句来完成“addq $ 4,%RAX”

环路由4个字节递增,而不是利用放大索引寻址模式的指针。


看看https://stackoverflow.com/questions/tagged/x86上的链接。此外,通过调试程序单步执行代码通常是确保您了解其功能的好方法。

+0

嘿彼得吧,我意识到这里不展开,远远晚于我张贴了这个。感谢澄清4字节的事情。 我要上很多东西读了。 同时,你能告诉我一步一步调试汇编代码而不是gdb的最佳方法吗? 我可以使用的任何其他编译器或方法或工具? – svm

+0

@sarath:任何调试器都应该能够单步执行。当先前的指令改变的寄存器被突出显示时,这很好。对于性能调优,性能计数器(Linux'perf')非常适合用来查看代码是否被你所期望的东西所阻塞。这取决于你想要做什么,但是看看优化编译器的asm输出,以及弄清楚为什么他们做了他们所做的事情通常很有用。 ESP。当你遇到他们*无法优化的情况时,你可能会意识到你需要给编译器更多的信息('__restrict__',alignment,unsigned) –