在GCC中使用“naked”属性来执行函数

时间:2010-04-26 21:05:37

标签: gcc attributes

GCC文档在6.30 Declaring Attributes of Functions中说明:

  

naked

     

在ARM,AVR,IP2K,RX和SPU端口上使用此属性表示指定的函数不需要编译器生成的序言/结尾序列。程序员需要提供这些序列。可以安全地包含在裸函数中的唯一语句是没有操作数的asm语句。应避免使用所有其他语句,包括局部变量声明,if语句等。应该使用裸函数来实现汇编函数的主体,同时允许编译器为汇编器构造必需的函数声明。

我可以使用裸函数的C语法安全地调用函数,还是只使用asm?

3 个答案:

答案 0 :(得分:5)

如果你在裸函数中做的唯一事情就是调用另一个函数,你只需使用一个JMP机器码指令。

你跳转到的函数将有一个有效的序言,它应该直接返回到裸函数的调用者,因为JMP不会在栈上推送返回地址。

答案 1 :(得分:5)

如果被调用的函数有完整的序言和结语,你可以安全地从裸函数调用函数。

请注意,断言您可以在裸函数中“安全地”使用汇编语言有点无稽之谈。您对使用汇编语言执行的任何操作负有全部责任,因为您对“安全”功能进行的任何调用都是如此。

为了确保您的通用被调用函数不是静态的或内联的,它应该在一个单独的编译单元中。

“裸”功能不包括任何序言或结语 - 他们是赤裸裸的。特别是,它们不包括堆栈上的局部变量操作,保存或恢复寄存器,或返回调用函数。

这并不意味着不存在堆栈 - 堆栈在程序初始化中初始化,而不是在任何函数初始化中。由于存在堆栈,因此称为函数序言和epilogues正常工作。函数调用可以安全地推送它的返回地址,使用的任何寄存器以及任何局部变量的空间。返回时(使用返回地址),将恢复寄存器并释放堆栈空间。

静态或内联函数可能没有完整的序言和尾声。它们可以并且可能依赖于调用函数来管理堆栈并恢复损坏的寄存器。

这导致了下一点:你需要prologue和epilogue来封装被调用函数的操作。如果被调用的函数也是安全的(没有显式或隐式的局部变量,也没有对状态寄存器的更改),它可以安全地静态和/或内联。与asm一样,您有责任确保这是真的。

答案 2 :(得分:0)

  

可以安全地包含在裸函数中的唯一语句是没有操作数的asm语句。应避免使用所有其他语句,包括声明局部变量,if语句等。

根据您已经给出的描述,我认为即使函数调用也不适合“naked”关键字。