2014-11-03 6 views
1

인라인 어셈블리 블록을 사용하여 배열을 정렬하는 c 코드의 문제가 있습니다. (가) 동안 무한 루프를하게 할 어떤 이유(+ r) 대 GCC x86 인라인 어셈블리의 제약

#include <stdio.h> 
#define n 20 

int main() 
{ 
    int array[n]; 
    int i; 
    int swapped; 

    printf("Enter the elements one by one \n"); 
    for (i = 0; i < n; i++) 
    { 
     scanf("%d", &array[i]); 
    } 

    printf("Input array elements \n"); 
    for (i = 0; i < n ; i++) 
    { 
     printf("%d\n", array[i]); 
    } 

    /* Bubble sorting begins */ 
    do 
    { 
      swapped = 0; 
      for (i = 1; i < n; i++) 
      { 
/* 
      if (array[i] < array [i-1]) 
      { 
       swapped =1; 
       int temp = array [i-1]; 
       array [i-1] = array [i]; 
       array[i] = temp; 
      } 
*/ 

       //body of the for loop 
       //converted to assembly 
       __asm__ __volatile__("cmp %0, %1;" 
            "jge DONE;" 
            "mov eax, %0;" 
            "mov %0, %1;" 
            "mov %1, eax;" 
            "mov %2, 1;" 
            "DONE: " 
            : "+r" (array[i]), "+r" (array[i-1]), "=r" (swapped) 
            : //no input 
            : "eax", "cc" 
            ); 


      } 

    } while (swapped > 0); 

    printf("Sorted array is...\n"); 
    for (i = 0; i < n; i++) 
    { 
     printf("%d\n", array[i]); 
    } 

    return 0; 
} 

,하지만 난 "+r" (swapped)swapped 변수에 대한 수정을 변경할 때 그것은 작동 :

내 전체 코드는 이것이다. 두 시나리오에 대해 생성 된 어셈블리 코드 (-save-temp)를 살펴본 결과 "+ r"이 사용 된 경우 레지스터에 변수 swapped을 이동하는 것 외에는 아무것도 알지 못했습니다.

"+r"을 사용해야합니까?

+0

나는 그런 점프를 작성 무서워 할 것이다. 컴파일러가 루프를 풀 었다고 상상해보십시오. 어디로 갈까요? 또한 인라인 asm을 작성하는 이유는 무엇입니까? 컴파일러는 C 코드에서 더 잘 생성되어야합니다. –

+0

'-masm = intel'으로 컴파일하고 있습니까? 명령 줄이 보이지 않습니다. –

+0

음, 내 유일한 목적은 GCC 인라인 어셈블리를 배우는 것입니다. 또한 __volatile__을 사용하고 -O0으로 코드를 컴파일하여 이러한 종류의 최적화를 방지했습니다. – soofyaan

답변

1

=을 사용하는 경우 출력임을 의미하므로 작성해야합니다. 그러나 스왑이있는 경우에 대비해서 만 쓸 수 있습니다. 컴파일러는 어셈블러 블록이 덮어 쓸 새 값을 생성한다고 가정하기 때문에 사용했던 swapped = 0을 최적화합니다. 즉, 스왑이 없으면 컴파일러는 %2에 대해 새 값인 swapped으로 선택한 레지스터에있는 모든 가비지를 행복하게 사용하며 우연히 무한 루프를 생성합니다. 여기

는 일부 코드가 설명하는 것입니다

swapped = 0; 
/* this is the asm block */ 
{ 
    /* this is not initialized, because it's declared as output */ 
    int register_for_operand2; 
    if (array[i] < array[i - 1]) 
    { 
     /* body here */ 
     register_for_operand2 = 1; 
    } 
    /* the compiler generates this code for the output operand */ 
    /* this will copy uninitialized value if the above condition was false */ 
    swapped = register_for_operand2; 
} 
+0

수정하십시오. 나는 그걸 알아 냈고 대답을 게시하려고했습니다. 감사! – soofyaan

+0

디버깅하는 동안 이상한 동작을 느꼈습니다. 코드는 printf ("\ n")를 넣으면 여전히 "= r"(swapped)으로 동작합니다. while 조건을 평가하기 바로 전에. 왜 궁금 해서요? – soofyaan

+1

광대가 말했듯이, 레지스터에 있던 "쓰레기"를 사용할 것입니다. 분명히 printf는 (우연히) 원하는 값을 남겨두고 있습니다. 분명히 당신이 의존하고 싶은 행동이 아닙니다 ... –