2014-02-08 158 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 

任何想法子總是問題?????

感謝您的回覆。這是substring的c代碼,我忘了null終止字符串。感謝仙人掌和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

哪裏不能工作..?如果有什麼我會認爲這是因爲你不是空的 - 正確地終止字符串,這意味着它有點幸運,它可以工作。 – 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) 
         ); 
} 

編輯:請注意,這個實現是非常不理想,雖然寫在彙編。對於特定的體系結構而言,內存對齊和字大小對速度很重要,可能最好的方法是通過對齊機器大小的字來進行復制。首先將字大小爲1的字節逐個複製,然後將大部分字符串複製到字中,最後完成字大小爲1的字節。

我把這個問題當作內聯彙編和傳遞參數的excersize,而不是複製字符串的最佳方式。對於現代的C編譯器,預計將生成-O2更快的代碼。

+0

現在非常感謝你的工作 – Jianchen

+0

這是非常錯誤的。 ESI/RSI,EDI/RSI和ECX/RCX實際上都是通過movsb來修改的。他們需要是輸入和輸出類型約束。你也在模板中破壞了EAX/RAX,但沒有告訴GCC。如果您修改程序集模板中的某些內容,則需要確保編譯器知道。通過對此進行優化可能會非常糟糕。同樣,至少需要一個「內存」clobber(有一種替代方法,但並不容易),以確保在調用內聯模板之前將src和dest在內存中實現。 –