2012-09-16 43 views
2

下面的內聯彙編代碼有什麼問題嗎? 運行函數spinlock_lock時遇到「非法指令(核心轉儲)」。Inline Aseembly關於「非法指令(核心轉儲)」,我該怎麼辦

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"); 

回答

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需要內存操作數或here的討論,您可能需要看一下here,以獲得不帶彙編器的自旋鎖的替代gcc實現。

+0

你正在談論他的__ asm__ __volatile __( 「L」? 「MOVL%0,%% EAX;」 \t \t \t 「測試%% EAX,EAX %%;」 // \t \t \t「JNZ spinlock_lock ;」 \t \t \t 「JNZ升;」 \t \t \t \t:// 「= R」(一) \t \t \t \t: 「R」(鎖相> cmos_lock) \t \t \t \t:「eax」); – dykw

+0

@dykw是的,您的jnz將分支回函數入口點,您應該保持內聯彙編代碼中的分支。 –

+0

它不起作用。我嘗試評論「__asm__ __volatile__(」lock; cmpxchg %% edx,%0 \ n「」。非法指令消失,爲什麼? – dykw