C++ 为什么gcc和icc生成的程序集包含大量的;额外的;伪行动?

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

当我查看由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 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