1. 程式人生 > >VC內聯彙編實現strcpy+彙編效能分析

VC內聯彙編實現strcpy+彙編效能分析

使用內聯彙編來實現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;
 };
}

 

可以看到,如果自己用匯編來實現函式會有很明顯的效能提升。