【问题标题】:substring -- c inline assembly codesubstring -- c 内联汇编代码
【发布时间】:2014-02-08 05:33:02
【问题描述】:

我编写了一个代码,它使用 gcc 内联汇编获取字符串的子字符串。但是当我想获取长度为 8 的子字符串时总是会遇到问题。这是代码

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

【问题讨论】:

  • 哪里不工作..?如果有什么我认为是因为您没有正确地以空值终止字符串,这意味着它完全可以工作有点幸运。
  • 非常感谢。但有趣的是,只有当 eidx-sidx = 8 时才会出现问题,这意味着所需的子字符串的长度为 8。否则它很幸运。我还是想不通。

标签: c gcc assembly inline-assembly


【解决方案1】:

我认为它不起作用,因为汇编代码不会 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)
                         );
}

编辑:请注意,尽管是用汇编语言编写的,但此实现并不理想。对于特定的架构,内存对齐和字长对速度很重要,并且可能进行复制的最佳方法是对齐机器大小的字。首先一个一个地复制到 word size-1 字节,然后将字符串的大部分复制到 word 中,最后完成最后一个 word size-1 字节。

我认为这个问题是内联汇编和传递参数的一个练习题,而不是复制字符串的最佳方式。使用现代 C 编译器,预计使用 -O2 会生成更快的代码。

【讨论】:

  • 这是非常错误的。 ESI/RSI、EDI/RSI 和 ECX/RCX 实际上都被movsb 破坏(修改)。它们需要输入和输出类型约束。您还在模板中破坏了 EAX/RAX,但没有告诉 GCC。如果您修改程序集模板中的某些内容,则需要确保编译器知道。对此进行优化可能会非常糟糕。同样,您至少需要一个memory clobber(有另一种方法,但不是那么容易)以确保在调用内联模板之前将srcdest 实现到内存中。
猜你喜欢
  • 2015-03-17
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
  • 2021-08-16
  • 1970-01-01
  • 1970-01-01
  • 2015-02-21
  • 1970-01-01
相关资源
最近更新 更多