Chinaunix首页 | 论坛 | 博客
  • 博客访问: 50934
  • 博文数量: 5
  • 博客积分: 313
  • 博客等级: 入伍新兵
  • 技术积分: 85
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-14 14:36
文章分类

全部博文(5)

文章存档

2012年(3)

2011年(2)

分类: C/C++

2011-11-09 16:25:27

源代码直接Copy 见谅

据说这个是GNU的写法(my_strcpy2)
char * 
my_strcpy2 (dest, src)
     char *dest;
     const char *src;
{
  register char c;
  char * s = (char *)src;
  const int off = dest - s - 1;
  do{
      c = *s ;
      s[off] = c;
    }while (c != '\0');
  return dest;
}
另外一种写法来自GFree_Wind(my_strcpy1)

char* my_strcpy1(char *dest, const char *src)
{
    char *d = dest;
    register char c;
    do{
        c = *src ;
        *d = c;
    } while ('\0' != c);
    return dest;
}

根据 CFree_Wind 大牛的说法 (本人小菜)1的效率要高于2 详情如下

既然大牛说大家都是学习那我使用VS2008 捣鼓了一番
这个是第一种反汇编出来的 为了不影响统计排除了空行和不考虑编译器的优化
  1. char* my_strcpy1(char *dest, const char *src)
  2. {
  3. 004113D0 push ebp
  4. 004113D1 mov ebp,esp
  5. 004113D3 sub esp,0D8h
  6. 004113D9 push ebx
  7. 004113DA push esi
  8. 004113DB push edi
  9. 004113DC lea edi,[ebp-0D8h]
  10. 004113E2 mov ecx,36h
  11. 004113E7 mov eax,0CCCCCCCCh
  12. 004113EC rep stos dword ptr es:[edi]
  13.     char *d = dest;
  14. 004113EE mov eax,dword ptr [dest]
  15. 004113F1 mov dword ptr [d],eax
  16.     register char c;
  17.     do {
  18.         c = *src ;
  19. 004113F4 mov eax,dword ptr [src]
  20. 004113F7 mov cl,byte ptr [eax]
  21. 004113F9 mov byte ptr [c],cl
  22. 004113FC mov edx,dword ptr [src]
  23. 004113FF add edx,1
  24. 00411402 mov dword ptr [src],edx
  25.         *d = c;
  26. 00411405 mov eax,dword ptr [d]
  27. 00411408 mov cl,byte ptr [c]
  28. 0041140B mov byte ptr [eax],cl
  29. 0041140D mov edx,dword ptr [d]
  30. 00411410 add edx,1
  31. 00411413 mov dword ptr [d],edx
  32.     } while ('\0' != c);
  33. 00411416 movsx eax,byte ptr [c]
  34. 0041141A test eax,eax
  35. 0041141C jne my_strcpy1 24h (4113F4h)
  36.     return dest;
  37. 0041141E mov eax,dword ptr [dest]
  38. };
  39. 00411421 pop edi
  40. 00411422 pop esi
  41. 00411423 pop ebx
  42. 00411424 mov esp,ebp
  43. 00411426 pop ebp
  44. 00411427 ret
这个是2种写法的汇编
  1. char * my_strcpy2 (char *dest, const char *src)
  2. {
  3. 00411440 push ebp
  4. 00411441 mov ebp,esp
  5. 00411443 sub esp,0E4h
  6. 00411449 push ebx
  7. 0041144A push esi
  8. 0041144B push edi
  9. 0041144C lea edi,[ebp-0E4h]
  10. 00411452 mov ecx,39h
  11. 00411457 mov eax,0CCCCCCCCh
  12. 0041145C rep stos dword ptr es:[edi]
  13.     register char c;
  14.     char * s = (char *)src;
  15. 0041145E mov eax,dword ptr [src]
  16. 00411461 mov dword ptr [s],eax
  17.     const int off = dest - s - 1;
  18. 00411464 mov eax,dword ptr [dest]
  19. 00411467 sub eax,dword ptr [s]
  20. 0041146A sub eax,1
  21. 0041146D mov dword ptr [off],eax
  22.     do{
  23.         c = *s ;
  24. 00411470 mov eax,dword ptr [s]
  25. 00411473 mov cl,byte ptr [eax]
  26. 00411475 mov byte ptr [c],cl
  27. 00411478 mov edx,dword ptr [s]
  28. 0041147B add edx,1
  29. 0041147E mov dword ptr [s],edx
  30.         s[off] = c;
  31. 00411481 mov eax,dword ptr [s]
  32. 00411484 add eax,dword ptr [off]
  33. 00411487 mov cl,byte ptr [c]
  34. 0041148A mov byte ptr [eax],cl
  35.     }
  36.     while (c != '\0');
  37. 0041148C movsx eax,byte ptr [c]
  38. 00411490 test eax,eax
  39. 00411492 jne my_strcpy2 30h (411470h)
  40.     return dest;
  41. 00411494 mov eax,dword ptr [dest]
  42. };
  43. 00411497 pop edi
  44. 00411498 pop esi
  45. 00411499 pop ebx
  46. 0041149A mov esp,ebp
  47. 0041149C pop ebp
  48. 0041149D ret
分析:
第一种一共44行代码 第二种 48行代码 如果汇编的代码条数作为算法的效率那么真的是第一种效率高吗?

两段代码最主要的差异在这个位置
  1. *d = c;
  2. 00411405 mov eax,dword ptr [d]
  3. 00411408 mov cl,byte ptr [c]
  4. 0041140B mov byte ptr [eax],cl
  5. 0041140D mov edx,dword ptr [d]
  6. 00411410 add edx,1
  7. 00411413 mov dword ptr [d],edx
  1. s[off] = c;
  2. 00411481 mov eax,dword ptr [s]
  3. 00411484 add eax,dword ptr [off]
  4. 00411487 mov cl,byte ptr [c]
  5. 0041148A mov byte ptr [eax],cl

GNU 在循环里面 少用了 2条汇编指令
不是我崇洋媚外 确实这个地方相当精妙
使用堆栈平行的内存空间来节省 CPU所执行的指令数这个是非常精妙的

虽然我没有进行进一步的实际测试 但是 CFree_Wind 大牛我个人不同意您的说法 
如果循环仅执行一次那么您的效率要高但是如果忽略循环外面的代码影响那么GNU的算法效率是您的

10/12=80%左右
 可以断然 如果实际使用中 GNU的算法效率比第一种写法提高了 10%-20%

--------------------------------------------------------------------------------

补充:2011-11-09
By:Ndk
摘要:补充计时测试结果
------------------------------------------
在 30 左右的字符时 1 种确实比 第二种少用时 测试512个字符左右第二种方案 要t2/t1=0.99 左右
处理器比较好 (i3 4核心的) 看不出多大的差异 所以升级硬件配置也可以提高程序效率(做算法的悲剧啊)
有点跑题 具体如下图(多按了几个字符 -.- )


 
阅读(2467) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~