GCC汇编内联:仅具有内联汇编代码的函数体

时间:2017-07-25 01:55:38

标签: c gcc x86 inline-assembly

我正在尝试在我的C项目中重用一些汇编代码。假设我有一系列指令,我想将它们组织成一个函数:

void foo() {
  __asm__ (
   "mov %eax, %ebx"
   "push %eax"
   ...
   );
}

然而,一个障碍是在函数foo的编译汇编代码中,除了内联汇编代码之外,编译器还会为此函数生成一些序言指令,整个汇编程序将变为类似: / p>

foo:
   push %ebp          <---- routine code generated by compilers
   mov  %ebp, %esp    <---- routine code generated by compilers
   mov %eax, %ebx
   push %eax

根据我的使用场景,这样的例程代码实际上打破了内联程序集的原始语义。

所以这是我的问题,有什么方法可以阻止编译器生成那些函数序言和结尾指令,并且只包含内联汇编代码?

2 个答案:

答案 0 :(得分:2)

内联asm代码的重点是以一种理智的方式与C编译器的调度程序和寄存器分配器接口,为您提供一种方法来指定如何将汇编代码连接到编译器的约束求解机制。这就是为什么内联asm代码中包含特定寄存器很少有意义的原因;你想要使用约束来分配一些寄存器并让编译器告诉你它们是什么。

如果您真的想要编写独立的asm代码,通过系统ABI与您的其他程序进行通信,请将该代码写入您在项目中包含的单独.s(或.S)文件中,而不是试图使用内联asm代码。

答案 1 :(得分:2)

您提到使用gcc进行编译。 在这种情况下,您可以使用-O2优化级别。这将使编译器进行堆栈优化,如果你的内联汇编很简单,它就不会插入序言和结尾。虽然,在每种情况下都可能无法保证,因为优化会不断变化。 (我的gcc与-O2完成了。)

另一个选择是你可以将整个函数(包括foo:)放在程序集块中

__asm__ (
    "foo:\n"
    "mov ..."
);

使用此选项,您需要知道名称修改规范(如果有)。如果您希望函数是非静态函数,则还必须在函数启动之前添加.globl foo

最后,您可以检查函数声明中的gcc __attribute__ ((naked))属性。但正如MichaelPetch所提到的,这不适用于X86目标。