问题描述:

class myClass {
public:
void SetNumber(int nNumber) {
m_nInt = nNumber;
}
private:
int m_nInt;
}; int main(int argc, char* argv[],int _version)
{
myClass Test;
Test.SetNumber(5);
return 0;
}

  上述代码中,SetNumber是如何识别得出来m_nInt是类的成员变量???

分析:

  main函数反汇编:

;省略进入main函数的部分汇编代码
push 5
lea ecx, [ebp+var_4] ;此处的[ebp+var_4]指的是Test对象的首地址
call j_myClass__SetNumber
;省略调用Set_Number之后的汇编代码

  从上述汇编代码可以看得出来,在main函数调用成员函数SetNumber之前,编译器先将实参5压栈,然后将Test对象的首地址保持到寄存器ecx中,最后直接调用成员SetNumber。从汇编代码中,还可以看出SetNumber的函数名是经过了修改的。

  SetNumber函数反汇编:

var_44= dword ptr -44h
var_4= dword ptr -4
arg_0= dword ptr 8 ;参数的地址 ;下面是进入函数后,将上一层的调用者的信息保持,压栈。
push ebp
mov ebp, esp
sub esp, 44h
push ebx
push esi
push edi
push ecx
lea edi, [ebp+var_44]
mov ecx, 11h
mov eax, 0CCCCCCCCh
rep stosd
pop ecx ;恢复ecx,this指针。
mov [ebp+var_4], ecx
mov eax, [ebp+var_4]
mov ecx, [ebp+arg_0]
mov [eax], ecx ;赋值,m_nInt=nNumber
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
retn 4  ;被调用者自己恢复栈
myClass__SetNumber endp

  从上述的反汇编代码可以看出,在底层成员函数和普通函数是没有区别的。我们所看到的类和对象的概念是编译器提供的,也就是说在调用成员函数的时候,编译器做了一些“小动作”:利用寄存器ecx来保持对象的首地址(即this指针),并以寄存器传参的方式传递给成员函数,这种调用被称为__thiscall。(注意:并不是所有的成员函数调用都是通过ecx来实现的,得看具体的编译器)

  __thiscall和__stdcall都是被调用者自己恢复栈。但是两者的区别在于,前者使用到一个寄存器来传递对象的首地址,而非通过栈传递的方式。

最新文章

  1. PHP实现队列及队列原理
  2. 数据库表映射到MyEclipse的实体对象
  3. linux基础-第十七单元 Samba服务
  4. VS无法启动调试:“生成下面的模块时,启用了优化或没有调试信息“
  5. Linux下rz命令使用的实例详解
  6. jenkins插件 build timeout和build timestamp
  7. 实验12:Problem I: 成绩排序
  8. 在生产环境使用Docker部署应用
  9. linux更新系统之后,删除多余的开机启动项
  10. SPOJ #691. Hotel Floors
  11. PayPal 开发详解(一):注册PayPal帐号
  12. USACO Section 2.4: Fractions to Decimals
  13. [codility]Grocery-store
  14. 简单的SqlHelper
  15. linux安装redis-3.0.7
  16. [AH/HNOI2017]大佬
  17. 利用AOP实现SqlSugar自动事务
  18. iOS ----------NSDate 、CFAbsoluteTimeGetCurrent、CACurrentMediaTime 的区别
  19. Python之历史
  20. PAT 1057 数零壹

热门文章

  1. 【codevs1002】搭桥(prim)
  2. MapReduce-从HBase读取数据处理后再写入HBase
  3. HDU 5884 Sort(2016年青岛网络赛 G 二分+贪心+小优化)
  4. 找回J2EE 之再学习打卡记录
  5. php如何查看扩展是否开启
  6. hdu 1907 John(anti nim)
  7. nyojb 2359 巴什博弈变形
  8. mysql 数据备份及pymysql模块
  9. ServlertContext
  10. WinForm判断程序是否已经在运行,且只允许运行一个实例