Pregunta

I write a code that get substring of a string with gcc inline assembly. but always get problem when I want to get the substring whose length is 8. here is the code

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

}

here is the output

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

any idea?????

Thanks for reply. Here is the c code of substring and I forgot to null terminate the string. Thank cactus and bbonev! Wish someone else can learn from this thread.

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;
}
¿Fue útil?

Solución

I suppose its not working because the assembly code does not 0 terminate the result buffer.

I would always prefer the substring semantics with starting position and count, instead of two positions. People think little easier in such terms.

There is no need to return any value from this function.

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: Note that this implementation is quite suboptimal although written in assembly. For a particular architecture memory alignment and word size are important for speed and probably the best way to do the copy is by aligned machine size words. First copy up to word size-1 bytes one by one, then copy the big part of the string in words and finally finish the last up to word size-1 bytes.

I take the question as an excersize in inline assembly and passing parameters, not as the best way to copy strings. With modern C compilers its expected that with -O2 faster code will be generated.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top