问题描述:

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都是被调用者自己恢复栈。但是两者的区别在于,前者使用到一个寄存器来传递对象的首地址,而非通过栈传递的方式。

__thiscalll C++底层识别成员函数的更多相关文章

  1. C++反汇编第一讲,认识构造函数,析构函数,以及成员函数

    C++反汇编第一讲,认识构造函数,析构函数,以及成员函数 以前说过在C系列下的汇编,怎么认识函数.那么现在是C++了,隐含有构造和析构函数 一丶认识构造函数 高级代码: class MyTest { ...

  2. 成员函数指针与高性能C++委托

    1 引子 标准C++中没有真正的面向对象的函数指针.这一点对C++来说是不幸的,因为面向对象的指针(也叫做“闭包(closure)”或“委托(delegate)”)在一些语言中已经证明了它宝贵的价值. ...

  3. [转]成员函数指针与高性能的C++委托

    原文(作者:Don Clugston):Member Function Pointers and the Fastest Possible C++ Delegates 译文(作者:周翔): 成员函数指 ...

  4. 理解ATL中的一些汇编代码(通过Thunk技术来调用类成员函数)

    我们知道ATL(活动模板库)是一套很小巧高效的COM开发库,它本身的核心文件其实没几个,COM相关的(主要是atlbase.h, atlcom.h),另外还有一个窗口相关的(atlwin.h), 所以 ...

  5. C++ 对象成员函数(非静态方法)

    1.神奇的inline语法与语义 inline语义C99和C++98都有.之前在单源文件编写的时候一直没有发现问题,但是一考虑到多文件的链接,就发现矛盾了. 一些inline的原则: 1. inlin ...

  6. C++类成员函数

    c++的两大特色是多态和模板.其中多态是通过继承和虚函数来实现的,其中虚函数是通过每个对象里面的虚表来实现的.如果这个对象的类有虚函数,那么这个类就有一张虚表,存的是每个虚函数的入口地址,而这个类的每 ...

  7. 成员函数指针与高效C++委托 (delegate)

    下载实例源代码 - 18.5 Kb 下载开发包库文件 - 18.6 Kb 概要 很遗憾, C++ 标准中没能提供面向对象的函数指针. 面向对象的函数指针也被称为闭包(closures) 或委托(del ...

  8. 【OOP】C++ const成员函数

    预备知识 1.代码转换分析技巧 在早期某些编译器会将C++代码翻译为C代码,然后使用C编译器生成可执行文件.其中翻译的一个转化就是:将this指针显式添加到成员函数的第一个参数位置上,并在成员函数调用 ...

  9. C++模板编程中只特化模板类的一个成员函数

    模板编程中如果要特化或偏特化(局部特化)一个类模板,需要特化该类模板的所有成员函数.类模板中大多数成员函数的功能可能是一模一样的,特化时我们可能只需要重新实现1.2个成员函数即可.在这种情况下,如果全 ...

随机推荐

  1. 《机器学习基石》第一周 —— When Can Machine Learn?

    (注:由于之前进行了吴恩达机器学习课程的学习,其中有部分内容与机器学习基石的内容重叠,所以以下该系列的笔记只记录新的知识) <机器学习基石>课程围绕着下面这四个问题而展开: 主要内容: 一 ...

  2. mybaties mapping中if

    mapping中 if的简单使用 <insert id="addPassenger" resultMap="EmpResultMap" parameter ...

  3. ViewPagerAdapter

    ) { ; } } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } ...

  4. JAVA8新特性——接口定义增强

    JAVA9都要出来了,JAVA8新特性都没搞清楚,是不是有点掉队哦~ 接口定义增强 在JDK1.8以前,接口是定义的: 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法 ...

  5. intellij idea build时出现Artifact contains illegal characters的解决

    此处无法创建是因为Artifact的命名为大小写混合,将大写改为小写即可正常创建

  6. tp5定时器

    # 定时器 * * * * * cd /home/wwwroot/default/dexin/dragon && /usr/bin/php think order --option 1 ...

  7. C#验证类

    #region 是不是中国电话,格式010-85849685 /**////<summary> /// 是不是中国电话,格式010-85849685 ///</summary> ...

  8. Spring Boot入门——JPA

    JPA最大的特点就是可以根据@Entity自动创建你数据库表,用户只需要声明持久层的接口,不需要实现该接口 1.JPA概念 JPA全称Java Persistence API,JPA通过JDK5.0注 ...

  9. python基础4 - 判断(if)语句

    6. 判断(if)语句 6.1 if 判断语句基本语法 在 Python 中,if 语句 就是用来进行判断的,格式如下: if 要判断的条件: 条件成立时,要做的事情 …… 注意:代码的缩进为一个 t ...

  10. UML类图(三)-------实例

    实例分析1——登录模块 某基于C/S的即时聊天系统登录模块功能描述如下: 用户通过登录界面(LoginForm)输入账号和密码,系统将输入的账号和密码与存储在数据库(User)表中的用户信息进行比较, ...