【发布时间】:2012-01-12 13:14:58
【问题描述】:
我有一个用纯 C 编写的应用程序,其中混合了一些包含纯 ASM 的函数。裸属性不适用于 x86(为什么?为什么?!),并且我的 asm 函数不喜欢当序言和结尾弄乱堆栈时。是否有可能创建一个可以从 C 代码部分引用的纯汇编程序函数?我只需要这样的 ASM 函数的地址。
【问题讨论】:
-
你可以做this。使用适合您的 OS 功能使内存区域可执行。
我有一个用纯 C 编写的应用程序,其中混合了一些包含纯 ASM 的函数。裸属性不适用于 x86(为什么?为什么?!),并且我的 asm 函数不喜欢当序言和结尾弄乱堆栈时。是否有可能创建一个可以从 C 代码部分引用的纯汇编程序函数?我只需要这样的 ASM 函数的地址。
【问题讨论】:
只需在功能块外使用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;
}
PS:确保您了解平台的调用约定。很多时候你不能只是复制/过去的汇编代码。
PPS:如果您关心性能,请改用extended asm。扩展 asm 本质上将汇编代码内联到您的 C/C++ 代码中,并且速度更快,尤其是对于短汇编函数。对于较大的汇编函数,最好使用单独的汇编源文件,因此对于极少数需要指向小型汇编函数的函数指针的情况,此答案确实是一个技巧。
【讨论】:
asm() 外部功能块在c99 中似乎不起作用。
__asm 或__asm__ 而不是asm。
asm 的全局变量,它与这个 GCC 扩展冲突。但是以两个下划线开头的名称是为实现保留的(例如 GCC)。所以GCC扩展可以使用__asm和__asm__仍然符合标准,但不符合asm。
undefined reference to 'one' 并且不得不将声明更改为 int one() asm ("_one");(在 Linux 上)。
大家好消息。 GCC 开发人员终于为 x86 实现了 attribute((naked))。该功能将在 GCC 8 中提供。
【讨论】:
attribute((interrupts)) 以及相关的命令行选项 -mgeneral-regs-only 添加了对 x86 中断的支持。该实现还有一些不足之处,但它不再未实现。
当然,只需创建一个.s 文件(汇编源),它通过gas(汇编器)运行以创建一个普通的目标文件。
【讨论】:
.S 后缀(大写S),您的汇编代码也将被cpp 预处理。