【问题标题】:Use sparc extended asm in global function在全局函数中使用 sparc 扩展 asm
【发布时间】: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


【解决方案1】:

来自GCC Documentation

请注意,扩展 asm 语句必须在函数内部。只有基本的 asm 可能是外部函数(请参阅Basic Asm)。使用裸属性声明的函数也需要基本的 asm(参见 Function Attributes)。

因此,您的问题的答案是 - 不,不可能在全局上下文中的函数之外使用扩展的汇编器模板。正如你所发现的,基本的汇编语句是允许的。

【讨论】:

    猜你喜欢
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 2021-05-05
    • 1970-01-01
    • 1970-01-01
    • 2013-10-25
    • 2016-05-06
    • 2023-03-13
    相关资源
    最近更新 更多