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;
};
}
可以看到,如果自己用匯編來實現函式會有很明顯的效能提升。