2

下面的内联汇编代码有什么问题吗?运行函数 spinlock_lock 时遇到“非法指令(核心转储)”。

void spinlock_lock(struct spinlock * lock) {

    int a;
    __asm__ __volatile__("movl %0, %%eax;"
                         "test %%eax, %%eax;"
                         "jnz spinlock_lock;"
                         :"=r"(a)
                         :"r"(lock->cmos_lock)
                         :"eax");

    __asm__ __volatile__ ("lock; cmpxchg %%edx, %0\n"
                          :"=r"(a)
                          :"r"(lock->cmos_lock)
                          :"edx", "memory");
4

1 回答 1

2

问题是你的分支;通常(x86)被调用的函数会在执行任何其他代码之前将帧指针保存在堆栈中

您的jnz spinlock_lock分支将分支回整个函数的入口点,从而在返回到您的内联汇编程序之前再次保存帧指针。保存帧指针足够的时间,你会用完堆栈。更不用说如果你离开你的内联汇编器并在它之外分支,你的寄存器可能不再包含你认为它们所做的事情。

您可能应该在您的内联汇编器中放置一个标签,然后再返回到该标签。

此外,该指令可以对寄存器进行操作,但由于您使用的是寄存器操作数cmpxchg %edx, %0,因此无法组合使用。lock要进行lock cmpxchg工作,您需要将匹配参数约束从 更改rm

您可能想在这里查看关于lock cmpxchg需要内存操作数的讨论,或者在这里查看没有汇编器的自旋锁的替代 gcc 实现。

于 2012-09-16T21:47:48.790 回答