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

我正在尝试像这样使用内联汇编,对于全局variables,但编译器通过说明对saved_sp的未定义引用给出错误。

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

saved_sp全局声明为static long saved_sp (对于一个文件)。 我在这里犯了什么错误?

如果saved_spstatic ,但是它的工作原理是“undefined reference to saved_sp'”(这实际上是一个链接器错误,而不是一个编译器错误),但是编译器似乎认为saved_sp不是在源文件中使用,因此决定从传递给汇编器的编译代码中完全省略它。

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

你可以告诉gccsaved_sp被某些saved_sp的东西所使用,因此可以通过添加used属性来避免选择抛出它(参见变量属性的文档 ,大概在页面的中途),例如:

 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 $ 

(这是来自一个使用gcc 4.4.5的32位Debian挤压系统,这是我必须要处理的最接近的东西; -m64在你的系统中可能是不必要的。)

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

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

也许这个问题可能完全是另一回事(缺少#include所以saved_sp实际上没有定义? 编辑 :现在你说它是static ,我猜这不太可能)。

最好你可以使用输入和输出参数:

 __asm__ __volatile__ ( "movq %0, %%rsp\n\t" : : "r"(saved_sp) : "memory" ); 

通常在汇编阶段可能会有一些变量不是符号(例如,堆栈变量或寄存器),而且,您还想要打开整个内存,以确保没有堆栈变量在saved_sp后保存在寄存器中存储在RSP中。