2014-02-08 3 views
1

문자열의 부분 문자열을 gcc 인라인 어셈블리로 가져 오는 코드를 작성합니다. 나는 길이가 8. 여기에 코드substring-c 인라인 어셈블리 코드

static inline char * asm_sub_str(char *dest, char *src, int s_idx, int edix) 
{ 
    __asm__ __volatile__("cld\n\t" 
         "rep\n\t" 
         "movsb" 
         : 
         :"S"(src + s_idx), "D"(dest), "c"(edix - s_idx + 1) 
         ); 
    return dest; 
} 

int main(int argc, char *argv[]) 
{ 

    char my_string[STRINGSIZE] = "abc defghij"; 
    char asm_my_sub_string[STRINGSIZE]; 

    int sidx,eidx; 

    sidx = 0; 
    eidx = 5; 
    char *d1 = asm_sub_str(asm_my_sub_string, my_string, sidx, eidx); 
    printf("d1[%d-%d]: %s\n",sidx, eidx, d1); 

    sidx = 0; 
    eidx = 7; 
    d1 = asm_sub_str(asm_my_sub_string, my_string, sidx, eidx); 
    printf("d1[%d-%d]: %s\n",sidx, eidx, d1); 

    sidx = 0; 
    eidx = 9; 
    d1 = asm_sub_str(asm_my_sub_string, my_string, sidx, eidx); 
    printf("d1[%d-%d]: %s\n",sidx, eidx, d1); 

} 

가 여기에 출력

d1[0-5]: abc de 
d1[0-7]: abc defg? 
d1[0-9]: abc defghi 

어떤 생각이 문자열을 취득 할 때 항상 문제를 얻을 ?????

답장을 보내 주셔서 감사합니다. 여기에 부분 문자열의 C 코드가 있는데 문자열을 종료하는 것을 잊어 버렸습니다. 선인장과 bbonev 감사드립니다! 누군가가이 스레드에서 배울 수 있기를 바랍니다.

static inline char * sub_str(char *dest, char *src, int s_idx, int edix) 
{ 
    int length = edix - s_idx + 1; 
    int i; 

    for(i = 0; i < length; i++) 
    { 
     *(dest + i) = *(src + s_idx + i); 
    } 
    *(dest + length) = '\0'; 

    return dest; 
} 
+0

어디에서 작동하지 않습니까? 내가 문자열을 올바르게 null로 끝내지 않았기 때문에 아무 것도 없다고 가정 할 수 있습니다. 이는 운좋게도 작동한다는 것을 의미합니다. – cactus1

+0

정말 고마워요. 그러나 eidx-sidx = 8 일 때만 문제가 발생한다는 것은 흥미 롭습니다. 이는 원하는 부분 문자열의 길이가 8이라는 것을 의미합니다. 그렇지 않으면 운좋게 작동합니다. 나는 아직도 이것을 알 수 없다. – Jianchen

답변

0

어셈블리 코드가 결과 버퍼를 종료하지 않기 때문에 작동하지 않는 것으로 가정합니다.

필자는 항상 두 위치 대신 시작 위치와 개수를 사용하여 부분 문자열 의미를 선호합니다. 사람들은 그렇게 쉽게 생각하지 않습니다.

이 함수에서 값을 반환 할 필요는 없습니다.

static inline void asm_sub_str(char *dest, char *src, int s_idx, int count) 
{ 
    __asm__ __volatile__("cld\n" 
         "rep\n" 
         "movsb\n" 
         "xor %%al,%%al\n" 
         "stosb\n" 
         : 
         :"S"(src + s_idx), "D"(dest), "c"(count) 
         ); 
} 

EDIT :이 구현은 어셈블리로 작성되었지만 상당히 차선입니다. 특정 아키텍처의 경우 메모리 정렬과 워드 크기가 속도면에서 중요하며 아마 복사를 수행하는 가장 좋은 방법은 기계 크기 단어를 정렬하는 것입니다. 먼저 단어 크기 - 1 바이트를 하나씩 복사 한 다음 문자열의 큰 부분을 단어로 복사하고 마지막으로 단어 크기 -1 바이트까지 마칩니다.

저는 문자열을 복사하는 가장 좋은 방법이 아니라 인라인 어셈블리와 매개 변수 전달에서 excersize로 질문을합니다. 현대의 C 컴파일러에서는 -O2보다 빠른 코드가 생성 될 것으로 예상됩니다.

+0

정말 고마워요. – Jianchen

+0

이것은 매우 잘못되었습니다. ESI/RSI, EDI/RSI, ECX/RCX는 실제로'movsb '에 의해 모든 clobbered (수정)됩니다. 입력 및 출력 유형 제약 조건이 필요합니다. 당신은 또한 템플릿에서 EAX/RAX를 clobbered했지만 GCC에 말하지 않았습니다. 어셈블리 템플릿 내에서 무언가를 수정하면 컴파일러가 알고 있는지 확인해야합니다. 이것에 대한 최적화는 꽤 나쁘게 나빠질 것입니다. 또한 인라인 템플릿이 호출되기 전에'src'와'dest'가 메모리에 구현되어 있는지 확인하는'메모리'클로버 (다른 방법이 있지만 쉽지는 않음)가 최소한 필요합니다. –