C++ 为什么gcc和icc生成的程序集包含大量的;额外的;伪行动?
当我查看由gcc或icc生成的程序集时,会发现大量的伪操作。他们都做了些什么吗 下面的例子提出了这个问题。我有两个简单的C++文件。一个调用函数,另一个执行 call.cpp:C++ 为什么gcc和icc生成的程序集包含大量的;额外的;伪行动?,c++,gcc,assembly,icc,C++,Gcc,Assembly,Icc,当我查看由gcc或icc生成的程序集时,会发现大量的伪操作。他们都做了些什么吗 下面的例子提出了这个问题。我有两个简单的C++文件。一个调用函数,另一个执行 call.cpp: #include <iostream> void vadd(float* __restrict__ A, float* __restrict__ B, float* __restrict__ C); int main(int argc, char* argv[]) { constexpr con
#include <iostream>
void vadd(float* __restrict__ A, float* __restrict__ B, float* __restrict__ C);
int main(int argc, char* argv[]) {
constexpr const size_t size = 16;
constexpr const size_t alignment = 16;
float* A;
posix_memalign((void**)&A, alignment, sizeof(float)*size);
A[ 0] = 0;
A[ 1] = 1;
A[ 2] = 2;
A[ 3] = 3;
A[ 4] = 4;
A[ 5] = 5;
A[ 6] = 6;
A[ 7] = 7;
A[ 8] = 8;
A[ 9] = 9;
A[10] = 10;
A[11] = 11;
A[12] = 12;
A[13] = 13;
A[14] = 14;
A[15] = 15;
float* B;
posix_memalign((void**)&B, alignment, sizeof(float)*size);
B[ 0] = 0;
B[ 1] = 10;
B[ 2] = 20;
B[ 3] = 30;
B[ 4] = 40;
B[ 5] = 50;
B[ 6] = 60;
B[ 7] = 70;
B[ 8] = 80;
B[ 9] = 90;
B[10] = 100;
B[11] = 110;
B[12] = 120;
B[13] = 130;
B[14] = 140;
B[15] = 150;
float* C;
posix_memalign((void**)&C, alignment, sizeof(float)*size);
vadd(A, B, C);
for (int i=0; i<(size-1); i++) {std::cout << C[i] << " ";}
std::cout << C[(size-1)] << std::endl;
}
当我使用icc编译并检查do.cpp的输出时,我看到大量的伪操作伴随着程序集。与我看过的其他文件相比,这个示例非常温和,这些文件包含比操作码多得多的伪操作,通常有数百行.byte操作
L_TXTST0:
# -- Begin __Z4vaddPfS_S_
# mark_begin;
.align 4
.globl __Z4vaddPfS_S_
__Z4vaddPfS_S_:
# parameter 1: %rdi
# parameter 2: %rsi
# parameter 3: %rdx
L_B1.1: # Preds L_B1.0
L____tag_value___Z4vaddPfS_S_.1: #1.80
movups (%rdi), %xmm1 #2.10
movups 16(%rdi), %xmm3 #2.10
movups 32(%rdi), %xmm5 #2.10
movups 48(%rdi), %xmm7 #2.10
movups (%rsi), %xmm0 #2.18
movups 16(%rsi), %xmm2 #2.18
movups 32(%rsi), %xmm4 #2.18
movups 48(%rsi), %xmm6 #2.18
addps %xmm0, %xmm1 #2.18
addps %xmm2, %xmm3 #2.18
addps %xmm4, %xmm5 #2.18
addps %xmm6, %xmm7 #2.18
movups %xmm1, (%rdx) #2.2
movups %xmm3, 16(%rdx) #2.2
movups %xmm5, 32(%rdx) #2.2
movups %xmm7, 48(%rdx) #2.2
ret #18.1
.align 4
L____tag_value___Z4vaddPfS_S_.3: #
# LOE
# mark_end;
.section __DATA, __data
# -- End __Z4vaddPfS_S_
.section __DATA, __data
.globl __Z4vaddPfS_S_.eh
// -- Begin SEGMENT __eh_frame
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
__eh_frame_seg:
L.__eh_frame_seg:
EH_frame0:
L_fde_cie_0:
.long 0x0000001c
.long 0x00000000
.long 0x52507a01
.long 0x10780100
.short 0x9b06
.long ___gxx_personality_v0@GOTPCREL+0x4
.long 0x08070c10
.long 0x01900190
.short 0x0000
__Z4vaddPfS_S_.eh:
.long 0x0000001c
.long 0x00000024
.quad L____tag_value___Z4vaddPfS_S_.1-__Z4vaddPfS_S_.eh-0x8
.set L_Qlab1,L____tag_value___Z4vaddPfS_S_.3-L____tag_value___Z4vaddPfS_S_.1
.quad L_Qlab1
.long 0x00000000
.long 0x00000000
# End
.subsections_via_symbols
然而,大多数这些伪操作都可以被删除,并且程序似乎运行得很好。下面是do.cpp中的程序集的精简版本,我可以成功链接并运行该程序集:
.text
.align 4
.globl __Z4vaddPfS_S_
__Z4vaddPfS_S_:
movups (%rdi), %xmm1
movups 16(%rdi), %xmm3
movups 32(%rdi), %xmm5
movups 48(%rdi), %xmm7
movups (%rsi), %xmm0
movups 16(%rsi), %xmm2
movups 32(%rsi), %xmm4
movups 48(%rsi), %xmm6
addps %xmm0, %xmm1
addps %xmm2, %xmm3
addps %xmm4, %xmm5
addps %xmm6, %xmm7
movups %xmm1, (%rdx)
movups %xmm3, 16(%rdx)
movups %xmm5, 32(%rdx)
movups %xmm7, 48(%rdx)
ret
gcc还生成了大量的伪操作,但它们似乎有一种独特的风格,具有不同的指令优势。下面是一个典型的例子:
LASFDE3:
.long LASFDE3-EH_frame1
.quad LFB1402-.
.set L$set$8,LFE1402-LFB1402
.quad L$set$8
.byte 0
.byte 0x4
.set L$set$9,LCFI4-LFB1402
.long L$set$9
.byte 0xe
.byte 0x10
.byte 0x4
.set L$set$10,LCFI5-LCFI4
.long L$set$10
.byte 0xe
.byte 0x8
.align 3
我意识到这个问题实际上是数百个小问题,每个问题都有非常具体的答案,但是这些“额外”说明在幕后做了哪些工作?您看过文档了吗?它们不是指令,而是数据。您可以从标识符名称中看到其原因,EH表示异常处理。谷歌“GCC展开表格”了解更多信息。@HansPassant谢谢。我怎样才能理解这些标签的一般含义?谷歌帮不了多少忙。这是在Mac上,我通常使用gcc进行编译,我使用clang的汇编程序进行gcc编译(因为它将编译AVX指令)。谁会是资料员?
LASFDE3:
.long LASFDE3-EH_frame1
.quad LFB1402-.
.set L$set$8,LFE1402-LFB1402
.quad L$set$8
.byte 0
.byte 0x4
.set L$set$9,LCFI4-LFB1402
.long L$set$9
.byte 0xe
.byte 0x10
.byte 0x4
.set L$set$10,LCFI5-LCFI4
.long L$set$10
.byte 0xe
.byte 0x8
.align 3