GCC的naked属性的等效替代方案

12

我有一个使用纯 C 编写的应用程序,其中混合了一些包含纯汇编代码的函数。在 x86 架构中,无法使用 naked 属性(为什么?为什么!)而我的汇编函数不喜欢前言和后语干扰堆栈。是否有可能创建一个纯汇编函数,并可以从 C 代码部分引用它?我只需要这样 ASM 函数的地址。


你可以执行 这个操作。使用适合你的操作系统的函数将内存区域设置为可执行。 - Alexey Frunze
3个回答

17

只需在函数块外部使用asm()即可。 asm()的参数被编译器简单地忽略并直接传递给汇编器。 对于复杂的函数,使用单独的汇编源文件是避免笨拙语法的更好选择。

示例:

#include <stdio.h>

asm("_one:              \n\
        movl $1,%eax    \n\
        ret             \n\
");

int one();

int main() {
        printf("result: %d\n", one());
        return 0;
}

注意确保你理解平台的调用约定,很多时候你不能只是复制/粘贴汇编代码。

另外,如果你关心性能,请使用扩展的asm。扩展的asm本质上将汇编代码嵌入到你的C/C++代码中,速度更快,特别是对于短汇编函数。对于较大的汇编函数,单独的汇编源文件更加合适,所以这个答案实际上是针对需要一个指向小型汇编函数的函数指针的罕见情况而提供的技巧。


c99中,函数块外的asm()似乎无法工作。 - hauzer
1
@hauzer 请尝试使用 __asm__asm__ 而非 asm - Mackie Messer
2
@hauzer 一个可移植的 c99 程序可能有一个名为“asm”的全局变量,这会与 GCC 扩展冲突。但是以两个下划线开头的名称保留给实现(例如 GCC)。因此,GCC 扩展可以使用 __asm__asm__,仍然符合标准,但不能使用 asm - Mackie Messer
2
我遇到了错误 undefined reference to 'one',不得不将声明更改为 int one() asm ("_one");(在Linux上)。 - Ben C

7

大家好,好消息!GCC开发者终于为x86实现了attribute((naked))。该功能将在GCC 8中可用。


在某种程度上相关的事情。GCC 7.1添加了对x86中断的支持,使用attribute((interrupts))以及相关的命令行选项-mgeneral-regs-only。实现还有待改进,但它不再是完全未实现的了。 - Michael Petch

3
当然,只需创建一个名为.s的文件(汇编源码),然后通过汇编器gas运行该文件以创建普通的目标文件。

如果您使用.S后缀(大写S),则汇编代码也将被cpp预处理。 - Mackie Messer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接