我正在尝试像这样使用内联汇编,对于全局variables,但编译器通过说明对saved_sp的未定义引用给出错误。
__asm__ __volatile__ ( "movq saved_sp, %rsp\n\t" );
saved_sp全局声明为static long saved_sp
(对于一个文件)。 我在这里犯了什么错误?
如果saved_sp
是static
,但是它的工作原理是“undefined reference to saved_sp'”(这实际上是一个链接器错误,而不是一个编译器错误),但是编译器似乎认为saved_sp
不是在源文件中使用,因此决定从传递给汇编器的编译代码中完全省略它。
编译器不理解asm
块内的asm
代码; 它只是将其粘贴到它生成的汇编代码中。 所以它不知道asm
块是否引用了saved_sp
,并且如果C代码中没有其他东西读取它,则可以自由决定它是完全不用的 – 特别是如果您有任何优化选项启用。
你可以告诉gcc
, saved_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中。