首页
社区
课程
招聘
[原创]类成员函数作为CallBack函数时3种访问类成员变量的方法
发表于: 2011-3-25 16:08 14389

[原创]类成员函数作为CallBack函数时3种访问类成员变量的方法

2011-3-25 16:08
14389
这是我能想到的3种方法,当然肯定还有更高级的方法,因为本人学过一点汇编,所以其中两中方法涉及到内联汇编,但都很精短
第一种,就是设置类成员函数为静态函数,然后设置一个类指针参数用于接收,调用时传递一个类指针即可.
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
using namespace std;

class A
{
public:
    A():i(0){;}

    static void test1(A* pThis)
    {
        pThis->i++;
    }

    void checkout()
    {
        DWORD dwThreadID;
        CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&test1, this,  0,&dwThreadID);
    }
public:
    int i;
};

int _tmain(int argc, _TCHAR* argv[])
{
    A a;
    a.checkout();
    cout << a.i << endl;
    return 0;
}

但是,如果这个CALLBACK函数要访问的类成员变量太多,每次用类指针来访问有点麻烦,有什么办法可以简化吗?
下面来说说第2种方法,首先我们需要把static 关键字去掉,但是在传递类成员函数指针的代码上时发现,会提示“&”: 绑定成员函数表达式上的非法操作,这下我们就要用到内联汇编来传递类成员函数指针了
  void* p;
  __asm
  {
   mov eax,offset test2
   mov p,eax
  }
通过反调试发现,默认情况下,类成员函数的调用约定用的是__thiscall,会把类指针给ECX寄存器,然后保存在[ebp-8]地址,所以,第二种方法,我们只要传递一个类指针,然后把他放到[ebp-8]地址,就做到this指针的修复
下面是实现代码:
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
using namespace std;

class A
{
public:
    A():i(0){;}

    static void test1(A* pThis)
    {

        pThis->i++;
    }

    void test2(void *pThis)
    {
         __asm
         {
             mov eax,pThis
             mov dword ptr [ebp-8],eax; //[ebp-8] 为__thiscall调用约定时this存放地址
         }
        i++;
    }
    void checkout()
    {
        DWORD dwThreadID;
   
        CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&test1, this,  0,&dwThreadID);
        void* p;
        __asm
        {
            mov eax,offset test2
            mov p,eax
        }
        CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)p, this,  0,&dwThreadID);

    }
public:
    int i;
};

int _tmain(int argc, _TCHAR* argv[])
{
    A a;
    a.checkout();
    Sleep(100);//等待线程运行完毕
    cout << a.i << endl;
    return 0;
}

第3种和第2种类似,只需要把类成员函数调用约定改成__stdcall方式,编译出来的代码调试发现,内部调用类成员函数时会默认传递参数1为类成员指针,所以这次的CALLBACK函数不需要设置参数(注意,因为编译器会默认传递参数1为类指针,所以实际我们编写的时候,不需要给类成员函数设置一个参数)
#include "stdafx.h"
#include <iostream>
#include <Windows.h>
using namespace std;

class A
{
public:
    A():i(0){;}

    static void test1(A* pThis)
    {

        pThis->i++;
    }

    void test2(void *pThis)
    {
         __asm
         {
             mov eax,pThis
             mov dword ptr [ebp-8],eax; //[ebp-8] 为_fastcall调用约定时this存放地址
         }
        i++;
    }

    void __stdcall /*WINAPI*/ test3()//这里没有参数,但内部调用时默认会传递一个参数进来当类指针
    {
        i++;
    }

    void checkout()
    {
        DWORD dwThreadID;
   
        CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)&test1, this,  0,&dwThreadID);
        void* p;
        __asm
        {
            mov eax,offset test2
            mov p,eax
        }
        CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)p, this,  0,&dwThreadID);
        __asm
        {
            mov eax,offset test3
            mov p,eax
        }
        CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)p, this,  0,&dwThreadID);

    }
public:
    int i;
};

int _tmain(int argc, _TCHAR* argv[])
{
    A a;
    a.checkout();
    Sleep(100);//等待线程运行完毕
    cout << a.i << endl;
    return 0;
}

第3种方法适用于CALLBACK函数不需要额外参数,只需要传递一个类指针的情况下,非常好用,如果你有更好的方法,不防一说,让大家也能学习学习~没技术含量的东西,做下笔记而已,让大家见笑了

[课程]FART 脱壳王!加量不加价!FART作者讲授!

收藏
免费 7
支持
分享
最新回复 (3)
雪    币: 154
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
默认情况下,类成员函数的调用约定用的是__fastcall

这个貌似是__thiscall
2011-3-25 17:37
0
雪    币: 656
活跃值: (448)
能力值: ( LV12,RANK:360 )
在线值:
发帖
回帖
粉丝
3
thiscall仅仅应用于“C++”成员函数。this指针存放于CX/ECX寄存器中,参数从右到左压。thiscall不是关键词,因此不能被程序员指定。

恩,说错了

谢谢啊~~
2011-3-25 17:48
0
雪    币: 220
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
呵呵 表示支持一下
2011-3-25 18:06
0
游客
登录 | 注册 方可回帖
返回
//