在GCC的内联汇编中,#define是什么意思?

4

我正在尝试在GCC中编写内联汇编,将#define中的值写入寄存器。

#define SOME_VALUE  0xDEADBEEF

void foo(void)
{
    __asm__("lis r5, SOME_VALUE@ha");
    __asm__("ori r5, r5, SOME_VALUE@l");
}

然而,当我编译时出现错误:

未定义的引用 `SOME_VALUE'

汇编程序有办法看到内联汇编中的 #define 吗?

我通过以下方式解决了这个问题:

#define SOME_VALUE  0xDEADBEEF
__asm__(".equ SOME_VALUE,   0xDEADBEEF");

void foo(void)
{
    __asm__("lis r5, SOME_VALUE@ha");
    __asm__("ori r5, r5, SOME_VALUE@l");
}

然而,我真的不想复制这个值。


2
正如你所看到的,__asm__ 接受一个字符串作为参数。因此,请考虑宏字符串化值/连接字符串。 - Eugene Sh.
只是提醒一下,你的示例完全不安全。如果你要破坏一个寄存器,你需要使用带有输出约束的扩展汇编。而且你应该在同一个汇编语句中放置多个指令;你不应该假设编译器会将你的汇编语句放在一起。 - Peter Cordes
1
所以,如果您已经在使用扩展的asm,您可以使用约束条件在任何体系结构上请求SOME_VALUE作为立即数。或者只需要求编译器将其放入r5中,使用register int foo asm("r5") = SOME_VALUE;,然后将其用作输入。或者,如果您不关心寄存器,则让编译器选择。 - Peter Cordes
@PeterCordes 没错,那只是一个愚蠢的例子。我意识到它有多不安全。但是感谢你指出来。未来的某个读者可能没有意识到这一点。 - user2976957
1个回答

6

在C语言中,可以使用一些预处理技巧来将值转换为字符串并实现字符串的续行:

#define SOME_VALUE  0xDEADBEEF
#define STR(x) #x
#define XSTR(s) STR(s)

void foo(void)
{
    __asm__("lis r5, " XSTR(SOME_VALUE) "@ha");
    __asm__("ori r5, r5, " XSTR(SOME_VALUE) "@l");
}

XSTR 将会被扩展成字符串 "0xDEADBEEF",并与其周围的字符串连接起来。

以下是演示: https://godbolt.org/z/2tBfoD


是的,但这似乎是一个 XY 问题,因为内联汇编会占用编译器的寄存器。请参阅我的问题评论;使用数字常量作为输入约束条件也应该可以,无论是作为立即数/字面值还是寄存器值。 - Peter Cordes

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