2017-07-25 310 views
1

我想重用我的C项目中一些汇编代码的函数体。假设我有一个指令序列,我想组织他们作为一个函数:GCC汇编内联:与只有内联汇编代码

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

然而,一个障碍是,在功能foo编译汇编代码,除了内联汇编代码,编译器也将产生这个功能有些序幕指令,整个汇编程序将成为类似:

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

由于我使用的情况下,这样的常规代码实际上打破了内联汇编的原始语义。

因此,这里是我的问题,有没有什么办法,我可以阻止编译器生成的函数序幕和尾声指令,并且仅包括内联汇编代码?

+3

不,你不能使用内联汇编的方式。只需在C项目中使用正常的程序集,这样就不会生成任何额外的指令。 –

+1

最好在程序集文件中创建函数,分别进行组装,然后将程序集对象链接到_C_文件。有人说这是可能做你在问什么。有一个[几个答案](https://stackoverflow.com/q/43310704/3857942)涉及到用这种方式写入中断处理程序的相关问题。您可以对任何您打算完全用汇编写入的_C_函数执行此操作。我强烈**推荐单独的程序集文件。 –

+1

@old_timer:有时用汇编代码(或至少是函数的一部分)编写裸C函数是有用的。我同意,但是,这是什么初学者(或某人不RTM)应该使用和明确什么对所有的代码要写入的方式.. – Olaf

回答

2

内联asm代码的全部要点是通过给你一种方法来指定如何将汇编代码连接到编译器的约束解决机器,以一种理智的方式与C编译器的调度程序和注册分配器进行交互。这就是为什么具有内置asm代码和特定寄存器的情况很少有意义;你反而想使用约束来分配一些寄存器,并让编译器告诉你它们是什么。

如果您确实想编写与系统ABI程序通信的独立asm代码,请将该代码写入您的项目中包含的独立.s(或.S)文件中,而不是比试图使用内联汇编代码。

+0

我真的不确定这是好还是不好的答案。没有pre/postamble的情况下,有用例可以拥有单个函数。但是,当然像OP这样编写一个完整的程序集项目似乎意图是一个非常糟糕的主意。如果你想要ABI,前/后导是必要的。 – Olaf

+0

@Olaf:然后将这个单一的函数写入一个单独的小的.s文件并将其链接到结果中。没有必要将所有东西放在一个甚至只是几个源文件中。 –

+0

您应该意识到,如果该函数仅用于单个编译单元,则会不必要地混淆全局命名空间并违反了局部性原则。这种做法是非常有争议的,即有见地。没有单一的,简单的答案。调用这种印象是没有更多信息的单一,普遍接受的解决方案是不光彩的。 (或许你没有注意到我试图区分不同的用例, – Olaf

2

你提到你使用gcc编译。 在这种情况下,您可以使用-O2优化级别。这将导致编译器进行堆栈优化,并且如果内联程序集很简单,它将不会插入序言和结尾。尽管这可能无法保证在任何情况下,因为优化不断变化。 (我的gcc用-O2做到了)。

另一种选择是,你可以把整个函数(包括foo:)组装块内的

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

有了这个选项,你需要知道的名字改编规格(如有)。如果您希望函数是非静态的,您还必须在函数启动之前添加.globl foo

最后你可以检查函数声明海合会__attribute__ ((naked))属性。但正如MichaelPetch所述,这不适用于X86目标。

+3

__attribute __((naked))'_GCC_不适用于x86目标。虽然这个问题没有用x86标记,但是显示的代码是x86。你应该在当前版本的_GCC_ –

+0

@MichaelPetch上得到'warning:'naked'attribute directive ignored ignored'的警告。谢谢,我将这一点转移到了最后,并添加了关于X86不可用的暗示。 –