如何在gcc内联汇编中使用全局变量

提问

我试图使用这样的内联汇编,作为全局变量,但编译器通过对saved_sp的未定义引用给出错误.

__asm__ __volatile__ (
        "movq saved_sp, %rsp\n\t" );

saved_sp被声明为static long saved_sp global(对于一个文件).我在这做什么错?

最佳答案

如果它失败并且“未定义引用`saved_sp’”(这实际上是一个链接器错误,而不是编译器错误)当saved_sp是静态的,但是当它不是时工作,那么编译器似乎已经确定saved_sp不是在源文件中使用,因此决定从传递给汇编程序的已编译代码中完全省略它.

编译器不理解asm块内的汇编代码;它只是将其粘贴到它生成的汇编代码中.因此,它不知道asm块引用saved_sp,如果C代码中没有其他内容可以从中读取,则可以自由决定它是否完全未使用 – 特别是如果您启用了任何优化选项.

你可以告诉gcc,saved_sp被它看不到的东西使用,因此通过添加used属性(参见documentation of variable attributes,大约在页面的中间位置),防止它选择扔掉它,例如:

static long __attribute__((used)) saved_sp;

这是一个完整的例子:

$cat test.c
#ifdef FIXED
static long __attribute__((used)) saved_sp;
#else
static long saved_sp;
#endif

int main(void)
{
  __asm__ __volatile__ (
        "movq saved_sp, %rsp\n\t" );
}

$gcc -m64 -o test test.c
$gcc -m64 -O1 -o test test.c
/tmp/ccATLdiQ.o: In function `main':
test.c:(.text+0x4): undefined reference to `saved_sp'
collect2: ld returned 1 exit status
$gcc -m64 -DFIXED -O1 -o test test.c
$

(这是来自32位Debian挤压系统,带有gcc 4.4.5,这是我最接近的东西; -m64在您的系统上可能是不必要的.)