<img src="https://img-blog.csdn.net/20150121213734953?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvamlodDU5NA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" /></pre><pre name="code" class="cpp">// consoleTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
struct _A
{
int a;
int b;
virtual void f()
{
this->a = 1;
printf("%d, %d", a, b);
}
};
class _B
{
public:
virtual TCHAR* f(int x)
{
int c = x;
b = 1;
printf("%d, %d", a, b);
TCHAR *p = _T("返回值");
return p;
}
int a;
int b;
};
int main()
{
int iVal = 25;
TCHAR *p = _T("字符串变量");
int* pInt = &iVal;
int& iRef = iVal;
printf("*pInt = %d, iRef = %d/n", *pInt, iVal);
_A a;
_B b;
a.a = a.b = 25;
b.a = b.b = a.a + a.b;
a.f();
p = b.f(5);
return 1;
}
对应的反汇编代码
28: int main()
29: {
013F1420 push ebp ;//这个ebp是调用main函数的函数的栈帧底部
;保存ebp,基址指针ebp指向一个(将要调用的)函数的栈帧的底部。栈帧保存返回地址和局部变量。
013F1421 mov ebp,esp
;将esp放入ebp中,此时ebp和esp相同.esp是栈顶
;此时:栈中以esp为界,本函数的参数已经在栈中,本函数的局部变量将要入栈
013F1423 sub esp,114h
;写把esp往上移动一个范围
;等于在栈中空出一片空间来存局部变量
013F1429 push ebx
013F142A push esi
013F142B push edi
;保存三个寄存器的值
013F142C lea edi,[ebp-114h] ;lea取得偏移地址. edi通常在内存操作指令中作为“目的地址指针”使用
;把ebp-114h加载到edi中,目的是保存局部变量的区域
013F1432 mov ecx,45h ;//CX:计数暂存器 45h次
013F1437 mov eax,0CCCCCCCCh ;//AX累积暂存器 初始化4个字节(一个cc就是一个int 3)
013F143C rep stos dword ptr es:[edi]
;从ebp-114h开始的区域初始化成全部0CCCCCCCCh,就是int3断点,初始化局部变量空间
;rep指令的目的是重复其上面的指令. ECX的值是重复的次数.45h * 4 = 114h
;STOS指令的作用是将eax中的值拷贝到ES:EDI指向的地址.指令执行后edi会减小(df=1)或者增加(df=0)
30: int iVal = 25;
013F143E mov dword ptr [iVal],19h
;定义变量
31: TCHAR *p = _T("字符串变量");
013F1445 mov dword ptr [p],offset string L"\x5b57\x7b26\x4e32\x53d8\x91cf" (13F5758h) ;//offset获得偏移地址
;定义变量
32:
33: int* pInt = &iVal;
013F144C lea eax,[iVal]
013F144F mov dword ptr [pInt],eax
;定义变量
34: int& iRef = iVal;
013F1452 lea eax,[iVal]
013F1455 mov dword ptr [iRef],eax
;定义变量
35: printf("*pInt = %d, iRef = %d/n", *pInt, iRef);
013F1458 mov esi,esp //保存栈顶指针
;//下面的指针和引用做参数的反汇编代码是一样的
013F145A mov eax,dword ptr [iRef] ;//这里把变量地址保存到eax, iRef是指针地址(如果不是指针变量,则没有这一行)
013F145D mov ecx,dword ptr [eax] ;//这里把变量值保存到ecx,eax中是变量地址
013F145F push ecx ;//参数iRef入栈
013F1460 mov edx,dword ptr [pInt] ;//参考上面
013F1463 mov eax,dword ptr [edx] ; //参考上面
013F1465 push eax ;//参考上面
;(如果iVal做参数,则应该是下面这样的
;0134145A mov eax,dword ptr [iVal] //通过变量地址iVal,取值
;0134145D push eax //值入栈
;)
013F1466 push offset string "*pInt = %d, iRef = %d/n" (13F573Ch)
;第一个参数入栈,参数是倒续入栈的
013F146B call dword ptr [__imp__printf (13F82E4h)]
;调用函数
013F1471 add esp,0Ch
;//平栈
013F1474 cmp esi,esp
;//平栈后的栈顶指针与保存的栈顶指针比较,看看是否出错
;//出错调用__RTC_CheckEsp
013F1476 call @ILT+335(__RTC_CheckEsp) (13F1154h)
36:
37: _A a;
38: _B b;
013F147B lea ecx,[b]
013F147E call _B::_B (13F1177h)
;调用类_B的构造函数._A是结构体,没有构造函数
39:
40: a.a = a.b = 25;
013F1483 mov dword ptr [ebp-38h],19h
013F148A mov eax,dword ptr [ebp-38h]
013F148D mov dword ptr [a],eax
41: b.a = b.b = a.a + a.b;
013F1490 mov eax,dword ptr [a]
013F1493 add eax,dword ptr [ebp-38h]
013F1496 mov dword ptr [ebp-48h],eax
013F1499 mov ecx,dword ptr [ebp-48h]
013F149C mov dword ptr [ebp-4Ch],ecx
42:
43: a.f();
013F149F lea ecx,[a]
013F14A2 call _A::f (13F10FFh)
46: p = b.f();
009514A5 push 5
;参数入栈
001B14A7 lea ecx,[b]
;取对象地址,存入ecx-->这个就是this指针
001B14AA call _B::f (1B120Dh)
;//有对象地址,才能调用类的成员函数B::f
001B14AF mov dword ptr [p],eax
;p = 返回值
45:
46: return 0;
013F14AF xor eax,eax
;相当于mov eax 0,eax作为返回值
47: }
013F14B1 push edx
013F14B2 mov ecx,ebp
013F14B4 push eax
013F14B5 lea edx,[ (13F14D8h)]
013F14BB call @ILT+135(@_RTC_CheckStackVars@8) (13F108Ch)
013F14C0 pop eax
013F14C1 pop edx
013F14C2 pop edi
013F14C3 pop esi
013F14C4 pop ebx
;恢复原来寄存器的值,怎么“吃”进去,怎么“吐”出来
013F14C5 add esp,114h
;恢复ESP,对应上边的sub esp,44h
013F14CB cmp ebp,esp
;检查esp是否正常,不正常就进入下边的call里面debug
013F14CD call @ILT+335(__RTC_CheckEsp) (13F1154h)
;处理可能出现的堆栈异常,如果有的话,就会陷入debug
013F14D2 mov esp,ebp
013F14D4 pop ebp
;恢复原来的esp和ebp,让上一个调用函数正常使用
002314D5 ret
;将返回地址存入eip,转移流程
;如果函数有返回值,返回值将放在eax返回
20: virtual TCHAR* f(int x)//类_B的成员函数
21: {
001315D0 push ebp
001315D1 mov ebp,esp
001315D3 sub esp,0D8h
001315D9 push ebx
001315DA push esi
001315DB push edi
001315DC push ecx
001315DD lea edi,[ebp-0D8h]
001315E3 mov ecx,36h
001315E8 mov eax,0CCCCCCCCh
001315ED rep stos dword ptr es:[edi]
;上面是初始化局部变量区域
001315EF pop ecx
001315F0 mov dword ptr [ebp-8],ecx
;保存this指针,ecx是调用成员函数之前保存的
22: int c = x;
011D15F3 mov eax,dword ptr [x]
011D15F6 mov dword ptr [c],eax
24: a = 1;
013E15F9 mov eax,dword ptr [this] ;//取this指针地址
013E15FC mov dword ptr [eax+4],1 ;//this指针+4 去得第一个成员变量地址
22: printf("%d, %d", a, b);
001315F3 mov esi,esp
001315F5 mov eax,dword ptr [this]
001315F8 mov ecx,dword ptr [eax+8]
001315FB push ecx
001315FC mov edx,dword ptr [this]
001315FF mov eax,dword ptr [edx+4]
00131602 push eax
00131603 push offset string "%d, %d" (135768h)
00131608 call dword ptr [__imp__printf (1382E4h)]
0013160E add esp,0Ch
00131611 cmp esi,esp
00131613 call @ILT+335(__RTC_CheckEsp) (131154h)
23: TCHAR *p = _T("返回值");
00131618 mov dword ptr [p],offset string L"\x8fd4\x56de\x503c" (135770h)
24: return p;
0013161F mov eax,dword ptr [p]
;这里使用eax返回p指针
25: }
00131622 pop edi
00131623 pop esi
00131624 pop ebx
00131625 add esp,0D8h
;//平栈
0013162B cmp ebp,esp
;//与保存的栈顶指针比较
0013162D call @ILT+335(__RTC_CheckEsp) (131154h)
00131632 mov esp,ebp
00131634 pop ebp
00131635 ret
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<span style="font-family: Arial, Helvetica, sans-serif;">int main()</span>
{
int test = 0;
for (int i = 0; i < 100; ++i)
{
test += i;
}
if (test < 5000)
{
test = 5000;
}
else if (test < 6000)
{
test = 6000;
}
else
{
test *= 2;
}
return 0;
}
</pre><pre code_snippet_id="584914" snippet_file_name="blog_20150120_11_2334745" name="code" class="cpp">对应反汇编代码
</pre><p></p><pre code_snippet_id="584914" snippet_file_name="blog_20150120_13_4887210" name="code" class="plain">//下面是for和if,while和for基本一样
//比较简单
33: int main()
34: {
00CB1380 push ebp
00CB1381 mov ebp,esp
00CB1383 sub esp,0D8h
00CB1389 push ebx
00CB138A push esi
00CB138B push edi
00CB138C lea edi,[ebp-0D8h]
00CB1392 mov ecx,36h
00CB1397 mov eax,0CCCCCCCCh
00CB139C rep stos dword ptr es:[edi]
35: int test = 0;
00CB139E mov dword ptr [test],0
36: for (int i = 0; i < 100; ++i)
00CB13A5 mov dword ptr [i],0
;//初始化i
00CB13AC jmp main+37h (0CB13B7h)
;
00CB13AE mov eax,dword ptr [i]
00CB13B1 add eax,1
00CB13B4 mov dword ptr [i],eax
00CB13B7 cmp dword ptr [i],64h
;与100比较
00CB13BB jge main+48h (0CB13C8h)
;大于等于时,跳转到
37: {
38: test += i;
00CB13BD mov eax,dword ptr [test]
00CB13C0 add eax,dword ptr [i]
00CB13C3 mov dword ptr [test],eax
39: }
00CB13C6 jmp main+2Eh (0CB13AEh)
40:
41: if (test < 5000)
00CB13C8 cmp dword ptr [test],1388h
00CB13CF jge main+5Ah (0CB13DAh)
42: {
43: test = 5000;
00CB13D1 mov dword ptr [test],1388h
00CB13D8 jmp main+74h (0CB13F4h)
44: }
45: else if (test < 6000)
00CB13DA cmp dword ptr [test],1770h
00CB13E1 jge main+6Ch (0CB13ECh)
46: {
47: test = 6000;
00CB13E3 mov dword ptr [test],1770h
48: }
49: else
00CB13EA jmp main+74h (0CB13F4h)
50: {
51: test *= 2;
00CB13EC mov eax,dword ptr [test]
00CB13EF shl eax,1
00CB13F1 mov dword ptr [test],eax
52: }
53:
54:
55: return 0;
00CB13F4 xor eax,eax
56: }