代码之家  ›  专栏  ›  技术社区  ›  Atmocreations

编译后ASM优化丢失?

  •  2
  • Atmocreations  · 技术社区  · 15 年前

    不是说我现在处于那种情况,但我只是对答案感兴趣…

    假设你有一些代码写在C/C++中,你想手动修改它,在ASM中修改它。

    如果更改C/C++中的代码并从源重新编译会发生什么。当然,对刚编译的文件的优化会丢失。如何避免每次编译项目时都需要重新进行这些优化?是否为需要优化的部件创建单独的源文件,以使其不那么复杂?或者有什么自动工具来做这个…?我猜你不能使用diff/patch…

    请分享你的经历,谢谢

    7 回复  |  直到 15 年前
        1
  •  7
  •   Tarydon    15 年前

    在单独的asm文件中编写一些函数, 呼叫 这些功能来自您的C/C++代码。或者直接在C/C++代码中编写内联程序集。

    换句话说,你可以从一些C/C++代码中获取一些基本的ASM代码,但是在你开始调整它之后,你就删除了原来的C/C++代码。 代替 它与ASM代码一起使用,使用这两种方法之一。

        2
  •  7
  •   Kornel Kisielewicz    15 年前

    为什么不在内联汇编程序中重写代码的关键部分而不修改输出?如何做到这一点的方法因编译器而异——检查编译器文档。

    在MSVC:

    // asm_overview.cpp
    // processor: x86
    void __declspec(naked) main()
    {
        // Naked functions must provide their own prolog...
        __asm {
            push ebp
            mov ebp, esp
            sub esp, __LOCAL_SIZE
        }
    
        // ... and epilog
        __asm {
            pop ebp
            ret
        }
    }
    

    在海湾合作委员会:

     __asm__ ("movl %eax, %ebx\n\t"
              "movl $56, %esi\n\t"
              "movl %ecx, $label(%edx,%ebx,$4)\n\t"
              "movb %ah, (%ebx)");
    

    还要注意,在编译和优化之后进行ASM更改只适用于那些确切知道自己在做什么的人。编译器不仅以一种人类无法优化的方式(至少不是一个没有光计算器能力的人)优化结构,它还执行了一个我们可以做的更复杂的代码分析。

    相信你的编译器。这是您使用过的最伟大的工具;)。

        3
  •  4
  •   Eli Bendersky    15 年前

    修改编译器生成的程序集代码。修改它,就像修改任何自动生成的代码一样,这正是您发现自己的原因,是一个非常糟糕的主意。

    如果您希望通过在ASM中实现代码来手动优化代码的特定部分,则有两个选项:

    1. 首先将代码编写为asm代码,并将组装好的asm文件链接到可执行文件中。您可以先让编译器从C/C++生成程序集,然后修改它,如果这样可以节省时间的话。但从现在开始,在ASM级别管理此代码。
    2. 在C/C++代码中使用内联程序集。因为手工优化的ASM代码部分通常很小,所以这通常是最好的主意。在大多数编译器中使用内联asm非常简单。下面是一个简单的 snippet for GCC :

    int main(void)
    {
            int foo = 10, bar = 15;
            __asm__ __volatile__("addl  %%ebx,%%eax"
                                 :"=a"(foo)
                                 :"a"(foo), "b"(bar)
                                 );
            printf("foo+bar=%d\n", foo);
            return 0;
    }
    

    它很好地演示了如何将C代码与ASM结合起来,共享变量。

        4
  •  3
  •   Nick Meyer    15 年前

    如果您的编译器支持它,那么您可能正在寻找 inline assembly ?

        5
  •  2
  •   Richard Pennington    15 年前

    使用内联汇编的另一个很好的理由是:gcc样式的内联汇编为代码生成器提供了一系列信息(clobber、volatile等),代码生成器可以使用这些信息使您的汇编很好地适合(和内联!)进入你的C/C++代码,而不会失去优化的机会。


    编辑:

    例如,来自另一个答案的C代码:

    int main(void)
    {
        int foo = 10, bar = 15;
        __asm__ __volatile__("addl  %%ebx,%%eax"
                             :"=a"(foo)
                             :"a"(foo), "b"(bar)
                             );
        printf("foo+bar=%d\n", foo);
        return 0;
    }
    

    生产:

    ....
    movl    $15, %ebx
    movl    $10, %eax
    #APP
    addl  %ebx,%eax
    #NO_APP
    movl    %eax, 8(%esp)
    movl    $.str, (%esp)
    movl    %eax, 4(%esp)
    call    printf
    ....
    

    变量foo和bar保存在寄存器中,甚至从未存储在堆栈中。

        6
  •  2
  •   Dmitry    15 年前

    很抱歉,这不是对您问题的严格回答,但我相信制作编译器的人在ASM方面比我们大多数人都要好得多。因此,我更依赖于编译器做“正确的事情”,而不是在C++源代码中编写一些ASM代码。

    另一个理由是我不使用至少inline asm(但有时我喜欢 __asm int 3; 在代码中)是MS Visual Studio编译器不支持64位版本的内联ASM。

    还有最后一件事,你是否尝试过使用不同的算法进行优化,而不是假设GCC(它可以使用SSE_,无论什么_,当前的_版本优化)产生的ASM代码比你写的要差。

        7
  •  1
  •   Nikolai Fetissov    15 年前

    您可以链接到用汇编程序显式编写的模块,或者使用内联ASM。