VC内联汇编实现strcpy+汇编性能分析

来源:互联网 发布:tomcat1和apache整合 编辑:程序博客网 时间:2024/05/17 08:46

使用内联汇编来实现strcpy的两种思路:

static void _strcpy1( char *dst, char *src )
{
 __asm
 {
  push ecx;
  push eax;
  push esi;
  push edi;
  push ebx;
  pushfd;

  cld;
  or ecx, 0xffffffff;
  xor eax, eax;
  mov edi, dword ptr [ src ];
  repne scasb; //使用它SCASB来进行字符串长度的检测

  neg ecx; //ECX为字符串长度+1(这个1表示初始的0xffffffff),对其求补码。恰好为字符串+空字符总长度。

  //得到字符串长度,为了减少运行次数,如果字符串长度比较长的话,使用movsd+movsb来完成。否则就直接使用movsb来实现。
  
  mov esi, dword ptr [ src ];
  mov edi, dword ptr [ dst ];

  cmp ecx, 10;

  ja multi_mov;
  rep movsb;
  jmp _return;

multi_mov:
  mov ebx, ecx;
  shr ecx, 2;
  rep movsd;  //先以44字节长度的字单位来拷贝,后以1字节单位来拷贝。
  mov ecx, ebx;
  and ecx, 3;
  rep movsb;

_return:
  //恢复寄存器退出
  popfd;
  pop ebx;
  pop edi;
  pop esi;
  pop eax;
  pop ecx;
 }

 printf( "%s/n", dst );
}

 

static void _strcpy2( char *dst, char *src )
{
 __asm
 {
  push ecx;
  push eax;
  push esi;
  push edi;
  pushfd;

  cld;

  mov esi, dword ptr [ src ];
  mov edi, dword ptr [ dst ];

lod_ch:
  lodsb; //这次使用了lods和stos指令来完成字符串拷贝,相对效率低一些。如果在其中有一些字符处理的操作的话这段代码就是最合适的。
  stosb;
  cmp al, 0;
  loopne lod_ch;

  popfd;
  pop edi;
  pop esi;
  pop eax;
  pop ecx;
 }

 printf( "%s/n", dst );
}

下面是对C语言实现函数和汇编实现函数的性能比较,以memset为例。

这是用一般C代码实现的memset函数

char *memsetc (dst, value, count)
char *dst;
char value;
unsigned int count;

 while (count--)
  *dst++ = value;
 return(start);
}

 

以上C代码生成的汇编码为:

push        ebp 
mov         ebp,esp
sub         esp,44h
push        ebx 
push        esi 
push        edi 

//char *start = dst;

mov         eax,dword ptr [dst]
mov         dword ptr [start],eax

//while (count--)
while (count--)
mov         eax,dword ptr [count]
mov         ecx,dword ptr [count]
sub         ecx,1
mov         dword ptr [count],ecx
test        eax,eax
je          __memsetc+32h (432C12h)


//  *dst++ = value;
mov         eax,dword ptr [dst]
mov         cl,byte ptr [value]
mov         byte ptr [eax],cl
mov         edx,dword ptr [dst]
add         edx,1
mov         dword ptr [dst],edx
jmp         __memsetc+0Fh (432BEFh)


// return(start);
mov         eax,dword ptr [start]

//下面使用内联汇编实现memset功能,比较一下它们的性能特性。

char *__memset( char *mem, int value, unsigned long len )
{
 __asm
 {
  push edx;
  mov edx, len;
  
  test edx, edx;
  jz short toend;
  
  xor eax, eax;
  mov eax, value;

  push edi;
  mov edi, mem;

  cmp edx, 4;
  jb tail;

  mov ecx, edx;
  neg ecx;
  and ecx, 3;
  jz short dwords;

  sub edx, ecx;

adjust_loop:
  mov [edi], al;
  add edi, 1;
  sub ecx, 1;
  jnz adjust_loop;

dwords:
  movzx ecx, al;
  shl eax, 8;
  add eax, ecx;
  movzx ecx, ax;
  shl eax, 10h;
  add eax, ecx;

  mov ecx, edx;
  and edx, 3;  //tail bytes
  shr ecx, 2;  //dwords
  jz tail;

  rep stosd;

  test edx, edx;
  jz finish;

tail:
  mov [edi], al;
  add edi, 1;

  sub edx, 1;
  jnz tail;

finish:
  mov eax, mem;
  pop edi;
  pop edx;

toend:
  mov eax, mem;
  pop edx;
 };
}

 

可以看到,如果自己用汇编来实现函数会有很明显的性能提升。

 

 

原创粉丝点击