如何在asm内联语句中请求通用寄存器?

时间:2013-04-19 07:25:47

标签: c gcc assembly inline-assembly

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

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

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

1 个答案:

答案 0 :(得分:0)

通常这样做的方式是:

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部分中。

当然,如果编写特定于arch的寄存器需要一个自定义指令(即不能使用CPU通常用来初始化寄存器值的任何类型的“移动”或“加载”),你宁愿需要像:

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

所有这些显然只适用于被“普通”代码使用的寄存器(即在平台ABI之外/由平台ABI显式保留为全局/注册不是被编译的代码触及。)

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