下面的内联汇编代码有什么问题吗? 运行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");
答案 0 :(得分:2)
问题是你的分支;通常(x86)the called function will save the frame pointer on the stack before executing any other code。
您的jnz spinlock_lock
分支将分支回整个函数的入口点,从而在返回内联汇编程序之前再次保存帧指针。保存帧指针足够多次,你将耗尽堆栈。更不用说如果你通过在其外部分支离开你的内联汇编程序,你的寄存器可能不再包含你认为他们所做的。
您可能应该在内联汇编程序中放置一个标签,然后将其分支回来。
此外,指令cmpxchg %edx, %0
可以对寄存器进行操作,但由于您使用的是寄存器操作数,因此无法与lock
组合。要使lock cmpxchg
有效,您需要将匹配参数约束从r
更改为m
。
您可能需要查看lock cmpxchg
以讨论需要内存操作数的{{1}}或here以获取没有汇编程序的螺旋锁的替代gcc实现。