分析下列源码:
#include <windows.h>
DWORD _stdcall Function(DWORD dwP1, PVOID p2)
{
DWORD v1;
DWORD v2 = 3;
v1 = dwP1 + v2;
return v1;
}
int main()
{
Function(100,nullptr);
return 0;
}
转汇编 vs2012
#include <windows.h>
DWORD _stdcall Function(DWORD dwP1, PVOID p2)
{
00FE13D0 push ebp //ebp = 003EFDCC
00FE13D1 mov ebp,esp //ebp = esp = 003EFCF0
00FE13D3 sub esp,0D8h //esp = esp -512=003EFC18 扩充512字节
00FE13D9 push ebx //ebx = 7EFDE000
00FE13DA push esi //esi = 00000000
00FE13DB push edi //edi = 003EFDCC
00FE13DC lea edi,[ebp-0D8h]//edi = 003EFC18
00FE13E2 mov ecx,36h //ecx = 36h
00FE13E7 mov eax,0CCCCCCCCh//eax = 0CCCCCCCCh
//rep重复其上面的指令,ECX的值是重复的次数.
//stos将eax中的值拷贝到ES:EDI指向的地址(4字节dword). ecx值随着拷贝次数减少
//如果设置了direction flag, 那么edi会在该指令执行后减小, 如果没有设置direction flag, 那么edi的值会增加, 这是为了下一次的存储做准备.
00FE13EC rep stos dword ptr es:[edi]//即从内存003EFC18-003EFCEC值都为0CCCCCCCCh
DWORD v1;
DWORD v2 = 3;
//00FE13EE mov dword ptr [ebp-14h],3
00FE13EE mov dword ptr [v2],3
v1 = dwP1 + v2;
//00FE13F5 mov eax,dword ptr [ebp+8]
00FE13F5 mov eax,dword ptr [dwP1]
//00FE13F8 add eax,dword ptr [ebp-14h]
00FE13F8 add eax,dword ptr [v2]
//00FE13FB mov dword ptr [ebp-8],eax
00FE13FB mov dword ptr [v1],eax
return v1;
//00FE13FE mov eax,dword ptr [ebp-8]
00FE13FE mov eax,dword ptr [v1]
}
00FE1401 pop edi //edi = 003EFDCC
00FE1402 pop esi //esi = 00000000
00FE1403 pop ebx //ebx = 7EFDE000
00FE1404 mov esp,ebp //esp = ebp = 003EFCF0
00FE1406 pop ebp //ebp = 003EFDCC
00FE1407 ret 8//因为_stdcall 所以由被调用者平衡栈 +8
-----------------------------------------
int main()
{
00FE1420 push ebp
00FE1421 mov ebp,esp
00FE1423 sub esp,0C0h
00FE1429 push ebx
00FE142A push esi
00FE142B push edi
00FE142C lea edi,[ebp+FFFFFF40h]
00FE1432 mov ecx,30h
00FE1437 mov eax,0CCCCCCCCh
00FE143C rep stos dword ptr es:[edi]
Function(100,nullptr);
00FE143E push 0
00FE1440 push 64h
00FE1442 call 00FE11EA
return 0;
00FE1447 xor eax,eax
}
00FE1449 pop edi
}
00FE144A pop esi
00FE144B pop ebx
00FE144C add esp,0C0h
00FE1452 cmp ebp,esp
00FE1454 call 00FE113B
00FE1459 mov esp,ebp
00FE145B pop ebp
00FE145C ret//因为_cdecl,所以由调用者平衡栈 直接ret即可
内存栈显示:
地址 | 值 | 说明 |
003EFC0C | 003EFDCC | push edi(edi = 003EFDCC) |
003EFC10 | 00000000 | push esi(esi = 00000000) |
003EFC14 | 7EFDE000 | push ebx(ebx = 7EFDE000) |
003EFC18 | cccccccc | ESP = ESP - 0X0D8H(216) |
003EFC1C | cccccccc | |
003EFC20 | cccccccc | |
................ | ||
................ | ||
003EFCD4 | cccccccc | |
003EFCD8 | cccccccc | |
003EFCDC | 00000003 | mov [ebp-14h],3 |
003EFCE0 | cccccccc | |
003EFCE4 | cccccccc | |
003EFCE8 | 00000067 | mov [ebp-8],eax//103 |
003EFCEC | cccccccc | |
003EFCF0 | 003EFDCC | EBP = ESP = 003EFCF0 |
003EFCF4 | 00FE1447 | CALL Function下一条指令地址 EIP保存 |
003EFCF8 | 00000064 | push 64h |
003EFCFC | 00000000 | push 0 |
................ | ||
................ | ||
................ | ||
003EFDCC | 003EFE1C | EBP--main() |
003EFDD0 | 00FE1989 | 调用main函数返回后的下一条指令地址0x00fe1989 |
图形显示: