一、函数的实现
这个函数还是比较简单的,就不做多余的解释了,上代码:
int _myStrcmp( char * str1, char * str2 )
{
while ( *str1 != 0 && *str2 != 0 && *str1 == *str2 )
{
str1++;
str2++;
}
return ( *str1 == 0 && *str2 == 0 );
}
二、逆向分析
用IDA打开看看函数结构:
.text:004113C0 ; int __cdecl _myStrcmp(char *str1, char *str2)
.text:004113C0 ?_myStrcmp@@YAHPAD0@Z proc near ; CODE XREF: _myStrcmp(char *,char *)j
.text:004113C0
.text:004113C0 var_C4 = dword ptr -0C4h
.text:004113C0 str1 = dword ptr 8
.text:004113C0 str2 = dword ptr 0Ch
.text:004113C0
.text:004113C0 push ebp
.text:004113C1 mov ebp, esp
.text:004113C3 sub esp, 0C4h
.text:004113C9 push ebx
.text:004113CA push esi
.text:004113CB push edi
.text:004113CC lea edi, [ebp+var_C4]
.text:004113D2 mov ecx, 31h
.text:004113D7 mov eax, 0CCCCCCCCh
.text:004113DC rep stosd ; 上面是填充栈空间
.text:004113DE
.text:004113DE loc_4113DE: ; CODE XREF: _myStrcmp(char *,char *)+54j
.text:004113DE mov eax, [ebp+str1]
.text:004113E1 movsx ecx, byte ptr [eax] ; ecx = *str1
.text:004113E4 test ecx, ecx
.text:004113E6 jz short loc_411416 ; ecx == 0 ? 判断str1是否到结束符
.text:004113E8 mov eax, [ebp+str2]
.text:004113EB movsx ecx, byte ptr [eax]
.text:004113EE test ecx, ecx
.text:004113F0 jz short loc_411416 ; ecx = *str2 ecx == 0 ? 同上判断str2是否到达结束符
.text:004113F2 mov eax, [ebp+str1]
.text:004113F5 movsx ecx, byte ptr [eax]
.text:004113F8 mov edx, [ebp+str2]
.text:004113FB movsx eax, byte ptr [edx]
.text:004113FE cmp ecx, eax
.text:00411400 jnz short loc_411416 ; 取一字节带符号位扩展到4字节,*str1 == *str2 ?
.text:00411402 mov eax, [ebp+str1]
.text:00411405 add eax, 1
.text:00411408 mov [ebp+str1], eax ; str1++ 指针向前移动1字节
.text:0041140B mov eax, [ebp+str2]
.text:0041140E add eax, 1
.text:00411411 mov [ebp+str2], eax ; str2++ 指针向前移动1字节
.text:00411414 jmp short loc_4113DE ; 继续判断比较
.text:00411416 ; ---------------------------------------------------------------------------
.text:00411416
.text:00411416 loc_411416: ; CODE XREF: _myStrcmp(char *,char *)+26j
.text:00411416 ; _myStrcmp(char *,char *)+30j ...
.text:00411416 mov eax, [ebp+str1]
.text:00411419 movsx ecx, byte ptr [eax]
.text:0041141C test ecx, ecx
.text:0041141E jnz short loc_411436 ; *str1 == 0 ? 判断字符串str1是否到达末尾
.text:00411420 mov edx, [ebp+str2]
.text:00411423 movsx eax, byte ptr [edx]
.text:00411426 test eax, eax
.text:00411428 jnz short loc_411436 ; *str2 == 0 ? 判断字符串str2是否到达末
.text:0041142A mov [ebp+var_C4], 1 ; *str1 == 0 && *str2 == 0, 局部变量赋值为1
.text:00411434 jmp short loc_411440 ; 结果赋值到eax返回
.text:00411436 ; ---------------------------------------------------------------------------
.text:00411436
.text:00411436 loc_411436: ; CODE XREF: _myStrcmp(char *,char *)+5Ej
.text:00411436 ; _myStrcmp(char *,char *)+68j
.text:00411436 mov [ebp+var_C4], 0 ; *str1 != 0 或者 *str2 != 0, 局部变量赋值成0
.text:00411440
.text:00411440 loc_411440: ; CODE XREF: _myStrcmp(char *,char *)+74j
.text:00411440 mov eax, [ebp+var_C4] ; 结果赋值到eax返回
.text:00411446 pop edi
.text:00411447 pop esi
.text:00411448 pop ebx
.text:00411449 mov esp, ebp
.text:0041144B pop ebp
.text:0041144C retn
.text:0041144C ?_myStrcmp@@YAHPAD0@Z endp
看下结构图 ,结构很清晰
三、我们自己用汇编写一个
int _myStrcmp( char * str1, char * str2 )
{
__asm
{
____CMP:
mov ecx, [str1]
mov ah, byte ptr [ecx]
cmp ah, 0x0
je ___ENDLAB
mov ecx, [str2]
mov al, byte ptr [ecx]
cmp al, 0x0
je ___ENDLAB
cmp ah, al
jne ___ENDLAB
mov eax, [str1]
add eax, 0x1
mov [str1], eax
mov eax, [str2]
add eax, 0x1
mov [str2], eax
jmp ____CMP
___ENDLAB:
xor eax, eax
mov ecx, [str1]
movsx eax, byte ptr [ecx]
mov ecx, [str2]
movsx ecx, byte ptr[ecx]
sub eax, ecx
};
}