【问题标题】:How to ask for a general purpose register in an asm inline statement?如何在 asm 内联语句中请求通用寄存器?
【发布时间】:2013-04-12 12:57:55
【问题描述】:

有没有办法让 gcc 分配一个寄存器供 asm 内联内部使用?这是一个示例(在伪 asm 中),其中 r5 直接在 asm 中使用,但它可以是任何通用寄存器,它仅供内部使用,因此既不是输入也不是输出:

asm("load_immediate_value %%r5,0;"
    /* ... */
    "add_immediate_value %%r5,%%r5,42"
    /* ... */
    :
    :
    : "r5");

在这个例子中,我选择寄存器 r5 并通过 clobber 列表告诉 gcc 我正在使用它。但是如果 r5 是一个 ABI 寄存器呢?!我需要一种方法来简单地要求注册,而不必自己命名。

【问题讨论】:

  • EBI 寄存器如何成为通用寄存器?还是您的意思是 ABI / EABI (例如,如果您选择 ABI 指定需要在函数调用之间保留的寄存器怎么办)?
  • 是的,我指的是 ABI 而不是 EBI,抱歉

标签: c gcc assembly inline-assembly


【解决方案1】:

通常这样做的方式是:

static __inline__ void set_archctrl0(unsigned long val) {
    register unsigned long archctrl0 __asm__("archctrl0") = val;

    __asm__ __volatile__("" : "+r"(archctrl0) : : "cc", "memory");
}

empty asm 语句只是为了强制编译器优化整个事情。

或者,一个更实际的例子,读取堆栈指针寄存器可以这样完成:

static __inline__ void * getSP(void) {
    register void * sp asm("sp");
    asm ("" : "=r"(sp));
    return sp;
}

将变量绑定到特定寄存器的方法记录在 GCC 手册的Explicit Register Variables 部分。

当然,如果编写特定于架构的寄存器需要自定义指令(即无法使用 CPU 通常用于初始化寄存器值的任何类型的“移动”或“加载”来完成),您宁愿需要类似:

static __inline__ void set_archctrl0(unsigned long val) {
    __asm__ __volatile__("setarchctrl0 %0" : : "r"(val) : "cc", "memory");
}

显然,所有这些仅适用于 被“正常”代码使用的寄存器(即在平台 ABI 之外/由平台 ABI 明确保留为全局变量/作为 regs 不用于被编译后的代码所触动)。

您不能以这种方式指示编译器“不使用通用寄存器”。据我所知,这在 gcc 中是不可能的。

【讨论】:

  • 您可以使用-ffixed-reg 选项告诉 gcc “不要使用寄存器”,但随后它将应用于整个模块。
猜你喜欢
  • 2013-07-04
  • 2016-04-03
  • 2018-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
相关资源
最近更新 更多