【发布时间】:2016-11-23 17:30:31
【问题描述】:
我正在尝试在不使用 c 原型的情况下编写汇编函数。 由于某种原因,gcc 似乎不允许在全局上下文中使用扩展 asm。
请考虑以下编译成功的代码:
void *g_var;
void foo()
{
asm ("stx %%i7, [%0]"
:"=r" (g_var));
}
当我也在尝试使用asm定义原型时,如下:
asm(".global foo2\n\t"
"foo2:\n\t");
asm ("stx %%i7, [%0]"
:"=r" (g_var));
编译器给我以下错误,好像扩展 asm 不能在全局上下文中使用。
foo.c:151:2: 错误:在 ':' 标记之前需要 ')' :"=r" (return_addr)); ^
请注意,当我如下不使用扩展asm时,编译器认可代码:
asm(".global foo2\n\t"
"foo2:\n\t");
asm("jmpl %o7 + 8, %g0\n\t");
谢谢。
【问题讨论】:
-
嗯。 为什么你要这样做?只使用
foo()有什么问题?特别是如果您将其标记为内联。 -
@DavidWohlferd 我也对此感到好奇,尽管在 x86 上它对引导加载程序很有用,因为 x86 不支持函数的 naked 属性。他可能试图避免任何序言和尾声代码。使用 ARM,我很确定您可以创建一个包含基本内联汇编的裸函数。如果您需要使该代码首先出现在二进制文件中,那么链接器脚本是您最好的朋友。
-
@MichaelPetch 我知道序言/尾声可能是个问题(
i7不是 sparc 的堆栈指针吗?)。这就是我考虑内联的原因(即inline void foo (void) __attribute__((always_inline)))。似乎它比从这个顶级代码调用/返回更高效,而且不会让这个代码的未来维护者哭泣。 -
@DavidWohlferd,foo2 的目的是“挂钩”其他程序的现有内部闭源函数。这就是为什么内联不能满足我的原因。假设我们挂钩的函数是 bar。因此,该函数中的第一条指令将 jmp 到 foo2 挂钩,并且自动生成的结语可以覆盖 bar 寄存器。
-
啊。挂钩。这就说得通了。这也解释了为什么您不需要原型,因为您从未真正“调用”它。您对“bar”的实现可能会踩到寄存器,这似乎很奇怪。 sparc 没有通用的调用约定吗?也许我只是不明白你的钩子的细节(我没有必要这样做)。我想剩下的唯一问题是为什么用内联汇编而不是纯汇编来编写它。如果您将函数声明为 extern,您仍然可以从 c 中“找到”例程的地址。
标签: gcc assembly inline-assembly sparc