GCC文档声明在6.30声明函数属性:
naked在ARM,AVR,IP2K,RX和SPU端口上使用此属性可指示指定的函数不需要编译器生成的序言/结尾序列.程序员需要提供这些序列.可以安全地包含在裸函数中的唯一语句是
asm没有操作数的语句.if应避免使用所有其他语句,包括声明局部变量,语句等.应该使用裸函数来实现汇编函数的主体,同时允许编译器为汇编器构造必需的函数声明.
我可以使用裸函数中的C语法安全地调用函数,还是仅使用asm?
如果被调用的函数有完整的序言和结尾,你可以安全地从裸函数调用函数.
请注意,断言您可以在裸函数中"安全地"使用汇编语言有点无稽之谈.您对使用汇编语言执行的任何操作负有全部责任,因为您对"安全"功能进行的任何调用都是如此.
为了确保您的通用被调用函数不是静态的或内联的,它应该在一个单独的编译单元中.
"裸体"功能不包括任何序言或结语 - 他们是赤裸裸的.特别是,它们不包括堆栈上的局部变量操作,保存或恢复寄存器,或返回调用函数.
这并不意味着不存在堆栈 - 堆栈在程序初始化时初始化,而不是在任何函数初始化中.由于存在堆栈,因此称为函数序言和epilogues正常工作.函数调用可以安全地推送它的返回地址,使用的任何寄存器以及任何局部变量的空间.返回时(使用返回地址),将恢复寄存器并释放堆栈空间.
静态或内联函数可能没有完整的序言和尾声.它们可以并且可能依赖于调用函数来管理堆栈和恢复损坏的寄存器.
这导致了下一点:您需要序言和结语才能封装被调用函数的操作.如果被调用的函数也是安全的(没有显式或隐式的局部变量,也没有对状态寄存器的更改),它可以安全地静态和/或内联.与asm一样,您有责任确保这是真的.
如果你在naked函数中唯一做的就是调用另一个函数,你可以只使用一个JMP机器码指令.
您跳转到的函数将具有有效的序言,它应该直接返回到裸函数的调用者,因为JMP不会在堆栈上推送返回地址.