编译后ASM优化丢失了吗?

时间:2010-01-06 16:18:54

标签: c++ optimization assembly

不是说我目前处于那种情况,但我只是对答案感兴趣......

假设你有一些用C / C ++编写的代码,你想通过在ASM中修改它来手动优化它。

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

请分享您的经历,谢谢

7 个答案:

答案 0 :(得分:7)

您可以在单独的ASM文件中编写一些函数,并从C / C ++代码中调用这些函数。或者直接在C / C ++代码中编写内联汇编。

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

答案 1 :(得分:7)

为什么不在内联汇编程序中重写代码的关键部分,而不是修改输出?如何执行此操作的方法因编译器而异 - 请检查编译器文档。

在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更改只适用于那些完全了解自己正在做什么的人。编译器不仅以人类无法实现的方式优化结构(至少不是没有照明计算器能力的人),它还可以执行更复杂的代码分析。

信任您的编译器。这是你曾经使用的最好的工具;)。

答案 2 :(得分:4)

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

如果您希望通过在ASM中实施代码来特定部分代码,则有两种选择:

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

  3. 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结合,共享变量。

答案 3 :(得分:3)

如果你的编译器支持它,也许你正在寻找类似inline assembly的东西?

答案 4 :(得分:2)

对不起,对你的问题不是一个严格的答案,但我相信制作编译器的人在asm方面比我们大多数人好多了。因此,我更依赖编译器做“正确的事情”,而不是在c ++源代码中编写一些asm代码。

对于我不使用至少内联asm(有时我喜欢在代码中放置__asm int 3;)的另一个论点是MS Visual Studio编译器不支持64位构建的内联asm。

还有一件事,你是否尝试过使用不同的算法进行优化,而不是假设说gcc(可以使用SSE_whatever_is_the_current_version优化)会产生比你写的更差的asm代码。

答案 5 :(得分:2)

使用内联汇编的另一个好理由:gcc样式内联汇编为代码生成器提供了一堆信息(clobbers,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 :(得分:1)

您可以使用汇编程序显式编写的模块进行链接,也可以使用内联asm。