上一期,我们讨论了普通函数的调用过程,如果没弄明白,看这里
今天所要讲的将是对象调用函数。

 class C{public:int a;int b;int c;void f(int t){a = t;}};int _tmain(int argc, _TCHAR* argv[])
{C c;c.f(1);c.b = 2;return 0;
}

由于之前的普通函数的调用的基础,所以,接下来主要分析下面几个问题

对象调用如何传递对象到函数内
静态对象函数调用和普通对象函数调用有什么不同

int _tmain(int argc, _TCHAR* argv[])
{00654D30  push        ebp
00654D31  mov         ebp,esp
00654D33  sub         esp,0D8h
00654D39  push        ebx
00654D3A  push        esi
00654D3B  push        edi
00654D3C  lea         edi,[ebp-0D8h]
00654D42  mov         ecx,36h
00654D47  mov         eax,0CCCCCCCCh
00654D4C  rep stos    dword ptr es:[edi]
00654D4E  mov         eax,dword ptr ds:[0065F0E0h]
00654D53  xor         eax,ebp
00654D55  mov         dword ptr [ebp-4],eax  C c;c.f(1);
00654D58  push        1
00654D5A  lea         ecx,[c]
00654D5D  call        C::f (06510B9h)  c.b = 2;
00654D62  mov         dword ptr [ebp-10h],2  return 0;
00654D69  xor         eax,eax
}


通过上图可以看到,对象函数的传参和普通函数相同,使用,压栈式,不知道大家有没有注意到,这里存在两个疑点,(1)明明我是对象调用函数,编译器却作为静态函数调用模式调用。(2)编译器将c的地址传递给了EXC寄存器。我们就带着这俩个疑点继续向下看吧。
下面是C类的汇编

     void f(int t){00254420  push        ebp
00254421  mov         ebp,esp
00254423  sub         esp,0CCh
00254429  push        ebx
0025442A  push        esi
0025442B  push        edi
0025442C  push        ecx
0025442D  lea         edi,[ebp-0CCh]
00254433  mov         ecx,33h
00254438  mov         eax,0CCCCCCCCh
0025443D  rep stos    dword ptr es:[edi]
0025443F  pop         ecx
00254440  mov         dword ptr [this],ecx  a = t;
00254443  mov         eax,dword ptr [this]
00254446  mov         ecx,dword ptr [t]
00254449  mov         dword ptr [eax],ecx  }

通过上图可以看到,首先,函数内部将ECX寄存器内容压栈,然后初始化函数栈内容,
然后将ecx的值传入到dword ptr [this],最后完成赋值,实际在这里有个疑问,之前人们都说对象函数在编译期间将this指针作为第一个参数进行传递,如果是按照第一个参数传递,应该压栈才对,为啥这里没有压栈而实用寄存器进行传递。等下看看用静态函数看看如何吧。

static类函数

在上面的代买基础上添加了一个静态类函数,同时在调用两个函数之间通过汇编代码修改了ecx值,这个防止上一个函数调用对这部分有影响

 class C{public:int a;int b;int c;static int d;void f(int t){a = t;}static int t( ){return d;}};int C::d = 12;
int _tmain(int argc, _TCHAR* argv[])
{C c;c.f(1);c.b = 2;{_asm{mov ecx,10H}}c.t();return 0;
}


目前通过上图可以看到,静态函数的调用,连对象地址都没有传入。

     static int t( ){00A54370  push        ebp
00A54371  mov         ebp,esp
00A54373  sub         esp,0C0h
00A54379  push        ebx
00A5437A  push        esi
00A5437B  push        edi
00A5437C  lea         edi,[ebp-0C0h]
00A54382  mov         ecx,30h
00A54387  mov         eax,0CCCCCCCCh
00A5438C  rep stos    dword ptr es:[edi]  return d;
00A5438E  mov         eax,dword ptr ds:[00A5F024h]  }

通过上面的return的汇编代码可以看到,它是直接返回的ds:[00A5F024h]的数据,
我们重新编译可以发现&c= 0x0053FBD8

而上面ds:[00A5F024h]这个属于栈中的数据,

小结

1)学到这里,我们应该明白了成员方法调用时,在编译过程中,编译器会将对象的地址通过ecx寄存器传入到函数中,并通过地址访问对象的成员变量。
2)成员方法的调用最终都是转换为了静态函数调用,通过传递对象的地址来辨别不同类型的方法
3)实际静态成员函数也好,普通成员函数也好,调用都是通过我们上节函数调用类似,换汤不换药
4)静态成员函数调用过程中,编译器并没有传递对象的地址到函数中,这也是为什么静态成员函数无法调用普通成员变量的原因

老码识途之对象函数调用相关推荐

  1. 老码识途1之函数调用和局部变量

    无论在编程中,还是在面试中,都会遇见调用函数这个东东,但是,要是让你说函数是怎么调用的,你能回答上来吗,接下来就让我们一起探索函数如何在汇编层次上实现调用的 在接下来,我们将有几个问题要去解决 函数调 ...

  2. 老码识途:从机器码到框架的系统观逆向修炼之路 pdf电子书

    重要提示尊敬的用户您好,由于老码识途:从机器码到框架的系统观逆向修炼之路pdf书受百度网盘影响无法做公共分享,只能私密分享,有不到之处请多多谅解! 百度网盘链接: http://pan.baidu.c ...

  3. 《老码识途》读书笔记:第一章(上)

    <老码识途>读书笔记:第一章--欲向码途问大道,锵锵bit是吾刀(上)   1.赋值语句 对于全局变量赋值语句,例如下面这句: 1 int gi; 2 void main(int argc ...

  4. 老码识途学习笔记(一)

    第一章 全局变量引发的故事 1 程序存储区 程序存储区一般有下列几段: 程序代码区(SECTION.txt ): 用来存放可执行文件的操作指令(二进制),也就是说是它是可执行程序在内存中的镜像.代码段 ...

  5. 老码识途之构造函数和析构函数

    对象初始化过程就是先父类构造函数,再子类构造函数.,那么我们从汇编角度去探索这个过程是怎么样的 class P{public:int a ;P(){a = 1;}~P(){a = 4;} };clas ...

  6. 《老码识途:从机器码到框架的系统观逆向修炼之路》- 第1章 - 总结

    本章学到了什么 调试技巧:在VS中断点调试,查看反汇编代码,step into进行步进调试,运行过程中查看寄存器.内存地址.变量值变化等. 机器码构造能力:使用C/C++中的直接在C代码里写汇编语言的 ...

  7. 老码识途——在堆中构建mov和jmp指令

    // asmjmp.cpp : 定义控制台应用程序的入口点. // #include <stdio.h> #include <malloc.h>int gi; void * a ...

  8. 老码识途读书笔记 1

    知识点记录: 1.int 或指针类型的全局变量默认初始化为0,局部变量则为0xcccccccc.(win7 + vs2008 ) 2.内存溢出攻击即使用6个字节空间改变程序执行流程达到某种目的.话说当 ...

  9. 读书 --- 老码识途

    上周在图书馆借了这本书,这个周末细看了下,是本好书.作者应该是个大学教授叫韩宏.书中讲的很底层,一开始就告诉大家如何debug一段程序,在VS2008里面查看内存.寄存器.反汇编.通过这些来认识汇编. ...

最新文章

  1. VIM - 每行前或者每行后增加相同的字符串
  2. stdthread(8)并发recursive_mutex 递归锁
  3. string转object对象_025:听闻你精通面向对象,来解决一下
  4. Java实例开发教程:SpringBoot开发案例
  5. MPEG4 (ISO/IEC 14496) 文档内容 简介
  6. TIMING_05 VIVADO环境下的时序约束 之 基本时钟周期约束
  7. 舞伴配对问题java_舞伴配对问题
  8. Excel VBA遍历文件
  9. 与云原生及开源大神们的第二次亲密接触 | 全议程重磅发布
  10. wxpython开发教程_wxpython入门第十步(应用程序框架)
  11. 内存分布malloc/calloc/realloc/free/new/delete、内存泄露、String模板、浅拷贝与深拷贝以及模拟string类的实现
  12. Android开发笔记(八)神奇的shape
  13. 【Spring5.x】对象的生命周期、配置文件参数化、自定义类型转换器、后置处理Bean
  14. 学生管理系统(C语言)简单版
  15. GCC与交叉编译器(概念)
  16. QTTabBar 「资源管理器」让你的文件夹拥有浏览器标签页般的体验
  17. linux awr 日志,生成AWR报告
  18. Google 因果推断的CausalImpact 贝叶斯结构时间序列模型(二十二)
  19. RTMP推流摄像机联合EasyCVR安防视频云服务平台助力智能楼宇的建设
  20. grads 相关系数_气象统计方法实习报告材料

热门文章

  1. 无脑题分享:1163 阿克曼(Ackmann)函数
  2. 迷你型数字万用表使用说明
  3. java笔记之redis-缓存问题
  4. Linux下的显卡驱动安装
  5. 下载到的电子书格式是epub,这种格式能否在IOS手机上打开?
  6. 21天免费精通新概念1-4MP3
  7. 社区团购小程序开发 平邑网站建设网店制作
  8. spellman高压电源维修X4629高压发生器维修
  9. python监控网页更新_【小白教程】Python3监控网页
  10. 放假了,讲个真实的转岗故事