/*/
功能:由src所指内存区域复制count个字节到dest所指内存区域。
说明:src和dest所指内存区域可以重叠,但复制后dest内容会被更改。函数返回指向dest的指针。
/*/
#include "stdafx.h"
void *pmemmove(void *dest , void *src , int count);
int main(int argc, char* argv[])
{
//printf("Hello World!\n");
char a1[]="abcdefg";
char a2[10]={0};
printf("%s\n",a2);
pmemmove(a2,a1,5);
printf("%s\n",a2);
return 0;
}
void *pmemmove(void *dest , void *src , int count)
{
char *temp_dest=(char *)dest;
char *temp_src=(char *)src;
if (temp_dest<temp_src || temp_src+count<temp_dest)
{
// 没有重叠区域
//从高地址拷贝到低地址
while (count--)
{
*temp_dest=*temp_src;
temp_src++;
temp_dest++;
}
}
else
{
//有重叠区域
temp_src=temp_src+count-1;
temp_dest=temp_dest+count-1;
while(count--)
{
*temp_dest=*temp_src;
temp_src--;
temp_dest--;
}
}
return dest;
}
这个函数主要考虑到2段内存区域是否重叠。
判断是否重叠的逻辑分析如下图:
release模式编译,OD载入反汇编分析如下:
00401000 /$ 83EC 14 sub esp,14
00401003 |. A1 34704000 mov eax,dword ptr ds:[407034]
00401008 |. 8B0D 38704000 mov ecx,dword ptr ds:[407038] ; abcdefg赋值,存在eax/ecx中
0040100E |. 33D2 xor edx,edx ; edx=0
00401010 |. 894424 00 mov dword ptr ss:[esp],eax ; a1=abcdefg
00401014 |. 895424 09 mov dword ptr ss:[esp+9],edx ; a2[]={0};
00401018 |. 8D4424 08 lea eax,dword ptr ss:[esp+8] ; eac存放a2首地址
0040101C |. 895424 0D mov dword ptr ss:[esp+D],edx
00401020 |. 50 push eax
00401021 |. 68 30704000 push memmove.00407030 ; ASCII "%s
"
00401026 |. 894C24 0C mov dword ptr ss:[esp+C],ecx
0040102A |. C64424 10 00 mov byte ptr ss:[esp+10],0
0040102F |. 885424 19 mov byte ptr ss:[esp+19],dl
00401033 |. E8 78000000 call memmove.004010B0
00401038 |. 8D4C24 08 lea ecx,dword ptr ss:[esp+8] ; abcdefg存入ecx
0040103C |. 6A 05 push 5
0040103E |. 8D5424 14 lea edx,dword ptr ss:[esp+14] ; 将数组a2首地址存入edx
00401042 |. 51 push ecx
00401043 >|. 52 push edx ; 三个参数依次入栈
00401044 |. E8 17000000 call memmove.00401060 ; 调用函数(memmove)
00401049 |. 8D4424 1C lea eax,dword ptr ss:[esp+1C]
0040104D |. 50 push eax
0040104E |. 68 30704000 push memmove.00407030 ; ASCII "%s
"
00401053 |. E8 58000000 call memmove.004010B0
00401058 |. 33C0 xor eax,eax
0040105A |. 83C4 30 add esp,30
0040105D \. C3 retn
0040105E 90 nop
0040105F 90 nop
00401060 /$ 8B4424 04 mov eax,dword ptr ss:[esp+4] ; 将第一个参数(从左往右)存入eax(memmove函数的入口处)
00401064 |. 8B4C24 0C mov ecx,dword ptr ss:[esp+C] ; 将第三个参数存入ecx (5)
00401068 |. 56 push esi
00401069 |. 8B7424 0C mov esi,dword ptr ss:[esp+C] ; esi=abcdefg;
0040106D |. 3BC6 cmp eax,esi ; 参数1和参数2进行比较 这里esi存的是abcd首地址
0040106F |. 57 push edi
00401070 |. 8BD0 mov edx,eax
00401072 |. 72 24 jb short memmove.00401098 ; 参数1<=参数2,则跳
00401074 |. 8D3C0E lea edi,dword ptr ds:[esi+ecx]
00401077 |. 3BF8 cmp edi,eax ; 这里edi存的是“fg”字符串首地址
00401079 |. 72 1D jb short memmove.00401098 ; dest<src,跳
0040107B |. 8D57 FF lea edx,dword ptr ds:[edi-1]
0040107E |. 8D7408 FF lea esi,dword ptr ds:[eax+ecx-1]
00401082 |. 8BF9 mov edi,ecx
00401084 |. 49 dec ecx
00401085 |. 85FF test edi,edi
00401087 |. 74 24 je short memmove.004010AD
00401089 |. 8D79 01 lea edi,dword ptr ds:[ecx+1]
0040108C |> 8A0A /mov cl,byte ptr ds:[edx]
0040108E |. 4A |dec edx
0040108F |. 880E |mov byte ptr ds:[esi],cl
00401091 |. 4E |dec esi
00401092 |. 4F |dec edi
00401093 |.^ 75 F7 \jnz short memmove.0040108C
00401095 |. 5F pop edi
00401096 |. 5E pop esi
00401097 |. C3 retn
00401098 |> 8BF9 mov edi,ecx ; 进入while(n--)循环,开始拷贝内存数据
0040109A |. 49 dec ecx
0040109B |. 85FF test edi,edi
0040109D |. 74 0E je short memmove.004010AD
0040109F |. 2BF0 sub esi,eax
004010A1 |. 8D79 01 lea edi,dword ptr ds:[ecx+1]
004010A4 |> 8A0C16 /mov cl,byte ptr ds:[esi+edx]
004010A7 |. 880A |mov byte ptr ds:[edx],cl
004010A9 |. 42 |inc edx
004010AA |. 4F |dec edi
004010AB |.^ 75 F7 \jnz short memmove.004010A4
004010AD |> 5F pop edi
004010AE |. 5E pop esi
004010AF \. C3 retn
表示反汇编功底太差,看得我要死。。。。。。。