// Test1
typedef struct
{
int nValue;
BYTE nValue2[4];
}ST_TEST;
int main()
{
ST_TEST sTest1 = {0};
ST_TEST sTest2 = {0};
sTest2 = sTest1;
memcpy(&sTest2, &sTest1, sizeof(sTest1));
return 0;
}
// Disassembly
typedef struct
{
int nValue;
BYTE nValue2[4];
}ST_TEST;
int main()
{
004196B0 push ebp
004196B1 mov ebp,esp
004196B3 sub esp,0E4h
004196B9 push ebx
004196BA push esi
004196BB push edi
004196BC lea edi,[ebp-0E4h]
004196C2 mov ecx,39h
004196C7 mov eax,0CCCCCCCCh
004196CC rep stos dword ptr es:[edi]
004196CE mov eax,dword ptr [___security_cookie (428080h)]
004196D3 xor eax,ebp
004196D5 mov dword ptr [ebp-4],eax
ST_TEST sTest1 = {0};
004196D8 mov dword ptr [ebp-10h],0
004196DF xor eax,eax
004196E1 mov dword ptr [ebp-0Ch],eax
ST_TEST sTest2 = {0};
004196E4 mov dword ptr [ebp-20h],0
004196EB xor eax,eax
004196ED mov dword ptr [ebp-1Ch],eax
sTest2 = sTest1;
004196F0 mov eax,dword ptr [ebp-10h]
004196F3 mov dword ptr [ebp-20h],eax
004196F6 mov ecx,dword ptr [ebp-0Ch]
004196F9 mov dword ptr [ebp-1Ch],ecx
memcpy(&sTest2, &sTest1, sizeof(sTest1));
004196FC push 8
004196FE lea eax,[ebp-10h]
00419701 push eax
00419702 lea ecx,[ebp-20h]
00419705 push ecx
00419706 call @ILT+980(_memcpy) (4113D9h)
0041970B add esp,0Ch
return 0;
0041970E xor eax,eax
}
// Test2
typedef struct
{
int nValue;
BYTE bValue[4092];
}ST_TEST;
int main()
{
ST_TEST sTest1 = {0};
ST_TEST sTest2 = {0};
sTest2 = sTest1;
memcpy(&sTest2, &sTest1, sizeof(sTest1));
return 0;
}
// Disassembly
typedef struct
{
int nValue;
BYTE bValue[4092];
}ST_TEST;
int main()
{
004196B0 push ebp
004196B1 mov ebp,esp
004196B3 mov eax,20D4h
004196B8 call @ILT+415(__chkstk) (4111A4h)
004196BD push ebx
004196BE push esi
004196BF push edi
004196C0 lea edi,[ebp-20D4h]
004196C6 mov ecx,835h
004196CB mov eax,0CCCCCCCCh
004196D0 rep stos dword ptr es:[edi]
004196D2 mov eax,dword ptr [___security_cookie (428080h)]
004196D7 xor eax,ebp
004196D9 mov dword ptr [ebp-4],eax
ST_TEST sTest1 = {0};
004196DC mov dword ptr [ebp-1008h],0
004196E6 push 0FFCh
004196EB push 0
004196ED lea eax,[ebp-1004h]
004196F3 push eax
004196F4 call @ILT+510(_memset) (411203h)
004196F9 add esp,0Ch
ST_TEST sTest2 = {0};
004196FC mov dword ptr [ebp-2010h],0
00419706 push 0FFCh
0041970B push 0
0041970D lea eax,[ebp-200Ch]
00419713 push eax
00419714 call @ILT+510(_memset) (411203h)
00419719 add esp,0Ch
sTest2 = sTest1;
0041971C push 1000h
00419721 lea eax,[ebp-1008h]
00419727 push eax
00419728 lea ecx,[ebp-2010h]
0041972E push ecx
0041972F call @ILT+980(_memcpy) (4113D9h)
00419734 add esp,0Ch
memcpy(&sTest2, &sTest1, sizeof(sTest1));
00419737 push 1000h
0041973C lea eax,[ebp-1008h]
00419742 push eax
00419743 lea ecx,[ebp-2010h]
00419749 push ecx
0041974A call @ILT+980(_memcpy) (4113D9h)
0041974F add esp,0Ch
return 0;
00419752 xor eax,eax
}
通過上面的的兩份測試代碼,我們可以看出,結構的直接賦值(默認結構體賦值函數)與memcpy之間的異同.
例1中,結構體小於4096時,賦值是通過結構體中每個變量的賦值來完成的.
例2中,結構體大於等於4096時,結構體賦值與memcpy的效果是一樣的.因為我們通過代碼的反匯編,可以看出編譯器已經將代碼優化成一樣的匯編代碼了.
所以,理論上來說,針對結構體調用memcpy的效果與直接賦值基本上是一樣的.
而且按照匯編的結果,直接賦值的匯編代碼少於memcpy的匯編代碼,所以更推薦使用結構體的直接賦值(注意,這裡的結構體是指沒有重載賦值函數的)