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

Met*_*est 8 c linux assembly gcc inline-assembly

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

__asm__ __volatile__ (
        "movq saved_sp, %rsp\n\t" );
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*ery 6

如果失败,"未定义参考`saved_sp""(这是一个真正的连接时的错误,而不是一个编译器错误)saved_spstatic,但如果它不工作,那么它很可能是编译器已经决定,saved_sp在不使用你的源文件,因此决定从传递给汇编程序的已编译代码中完全省略它.

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

您可以通过添加属性(参见变量属性文档,大约在页面的中间位置)来判断gccsaved_sp是由无法看到的内容使用,从而防止它选择将其丢弃,例如:used

static long __attribute__((used)) saved_sp;
Run Code Online (Sandbox Code Playgroud)

这是一个完整的例子:

$ 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
$ 
Run Code Online (Sandbox Code Playgroud)

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


NPE*_*NPE 0

gcc 4.4.4正如我在评论中指出的,在 64 位 Ubuntu 上使用以下代码进行编译(并生成正确的机器代码) :

long saved_sp;

int main() {
  __asm__ __volatile__ (
        "movq saved_sp, %rsp\n\t" );
}
Run Code Online (Sandbox Code Playgroud)

也许问题可能完全是其他问题(缺少#include所以saved_sp实际上没有定义?编辑:既然你说它是static,我想这不太可能。)