2012-09-16 3 views
2

인라인 어셈블리 코드 아래에 문제가 있습니까? spinlock_lock 함수를 실행할 때 "잘못된 명령 (코어 덤프 됨)"이 발생했습니다.인라인 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이거나 어셈블러없이 스핀 록의 대체 gcc 구현에 대해서는 here을 참조하십시오.

+0

당신이 그의 __ asm__ __volatile __ ("L"에 대해 말을하는거야? "의 movl % 0, %% EAX;" \t \t \t "테스트 %% EAX, %% EAX;" // \t \t \t "JNZ spinlock_lock을 「 \t \t \t "JNZ의 L 「 \t \t \t \t : // '= R"(a) \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