当我尝试直接从 asm volatile 调用中访问静态变量时,我收到未定义的引用错误。我认为有一种方法可以在不使用输入和输出寄存器的情况下做到这一点,但是我的搜索结果是空的。
int main() {
static unsigned int a = 0;
__asm__ __volatile__("push a" : : :);
return 0;
}
error: undefined reference to a
确实是老问题,但是由于没有公认的答案...
首先,让我说使用内联 asm 通常是个坏主意。但如果你必须...
由于静态是在函数内部声明的,gcc 需要一些方法来区分a
main() 中命名的静态变量和 foo() 中的静态变量。它是如何做到的是实现定义的,但是在我机器上的构建中,它使用了名称 a.2499。所以使用:
__asm__ __volatile__("push a.2499" : : :);
工作。至少它做了一分钟。当我对周围的代码做了一些小改动时,它把它改成了 a.2500。当然,在执行此语句后不久,应用程序由于堆栈损坏而崩溃。
但是这种方法还有其他问题。其中一些来自 gcc文档中的这个声明:
GCC 自己不解析汇编指令,也不知道它们的含义,甚至不知道它们是否是有效的汇编输入。
结果,做:
a++;
__asm__ __volatile__("push a.2500" : : :);
a++;
不符合您的预期。即使是来自 -O1 的最小优化也将这两个a++
语句组合成一个addl $2, a.2500(%rip)
. 这样做是因为编译器看不到a
asm 中的使用情况,而使用a
作为输入的东西会提供。
您可以通过声明a
为 volatile 来解决此问题。您可以(可能)通过使用全局变量来解决命名问题。
但最好的解决方案(如果你真的必须使用内联 asm)只是指定a
为输入。我认为替代方案没有任何好处。
__asm__ __volatile__("push %0"
: /* no outputs */
: "g" (a) /* input as a register, memory, or immediate operand */
: /* no clobbers, because there's no way to tell gcc we're unbalancing the stack and clobbering the red-zone */
);
尝试:
__asm__ __volatile__ ("push " (a) : : :);
伙计,a
从双引号中删除
__asm__ __volatile__ ("push " (a) : : :);