内联汇编调用WINAPI函数调用类函数

int nums[] = {22,33,11,21,12,15,18,98}; std::vector<int> nums_vec(nums,nums+8); std::list<int> nums_list(nums,nums+8); /************************************************************************/ /* 定义一个 查找函数,返回它的地址 */ /************************************************************************/ // template <typename T> // const T * find(const T* first,const T* end,T value) // { // if (first==end) // { // return 0; // } // for (;first!=end;first++) // { // if (*first==value) // { // return first; // } // } // return 0; // } /************************************************************************/ /* 使用迭代器类型 */ /************************************************************************/ template <typename IteratorType,typename ElementType> IteratorType find(IteratorType first,IteratorType end,const ElementType &findValue) { while(first!=end) { if (*first==findValue){ return first; } ++first; } return NULL; } typedef int (CIteratorDlg::*func)(void);//定义类成员函数指针类型 void CIteratorDlg::OnBtnFind2() { // TODO: Add your control notification handler code here __asm mov ebx,ebx __asm mov ebx,ebx const int * pnum = find(nums,nums+8,(int)GetDlgItemInt(IDC_EDIT_FINDVALUE)); __asm mov eax,eax __asm mov eax,eax if (pnum) { char snum[5]; itoa(*pnum,snum,10); MessageBox(snum); } else { ::MessageBox(NULL,"没有找到这个数",NULL,MB_OK); } }

 

以上函数OnBtnFind2的反汇编分析:

 

 00401600 55 PUSH EBP ; prolog开始部分 00401601 8BEC MOV EBP,ESP ; 保存堆栈信息到EBP 00401603 83EC 08 SUB ESP,8 00401606 53 PUSH EBX ; EBX入栈,保护EBX 00401607 56 PUSH ESI ; ESI入栈,保护ESI 00401608 8BF1 MOV ESI,ECX ; 保存ECX,ECX中存放的是当前对象的地址 0040160A 8BDB MOV EBX,EBX ; 设置的花指令 0040160C 8BDB MOV EBX,EBX ; 设置的花指令 0040160E 6A 01 PUSH 1 ; 开始传递参数,第三个参数入栈[UINT GetDlgItemInt( int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE ) const;] 00401610 6A 00 PUSH 0 ; 开始传递参数,第二个参数入栈 00401612 68 E8030000 PUSH 3E8 ; 开始传递参数,第一个参数入栈 00401617 E8 90020000 CALL <JMP.&MFC42.#3095_?GetDlgItemInt@CWnd@@QBEIHPAHH@Z> ; 开始调用当前对象的成员函数[GetDlgItemInt,该函数的返回值存放在EAX中] 0040161C B9 20304000 MOV ECX,Iterator.00403020 ; 取得数组nums的首地址 00401621 3901 CMP DWORD PTR DS:[ECX],EAX ; 比较数组的当前元素的值是否和EAX的内容一致[EAX是上面GetDlgItemInt()调用的返回值] 00401623 74 0D JE SHORT Iterator.00401632 ; 如果相等说明找到匹配的数字那么结束循环跳转到地址401632执行 00401625 83C1 04 ADD ECX,4 ; 数组指针加一[数组成员是int类型,故每次迭代加4] 00401628 81F9 40304000 CMP ECX,Iterator.00403040 ; 判断是否到达数组最后一个元素的后面一位地址 0040162E ^ 75 F1 JNZ SHORT Iterator.00401621 ; 如果循环没有到达数组最后一位后面的地址那么跳转回地址401621继续比较操作 00401630 33C9 XOR ECX,ECX 00401632 8BC0 MOV EAX,EAX ; 设置的花指令 00401634 8BC0 MOV EAX,EAX ; 设置的花指令 00401636 85C9 TEST ECX,ECX 00401638 74 27 JE SHORT Iterator.00401661 ; 如果找到的指针为空则跳转到401661执行else块{if (pnum)} 0040163A 8B09 MOV ECX,DWORD PTR DS:[ECX] ; 将找到的整形值放入ECX寄存器 0040163C 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8] ; 取字符数组snum首地址到EAX {char snum[5];} 0040163F 6A 0A PUSH 0A ; 开始传递参数,第三个参数入栈 00401641 50 PUSH EAX ; 开始传递参数,第二个参数入栈 00401642 51 PUSH ECX ; 开始传递参数,第一个参数入栈 00401643 FF15 A8214000 CALL DWORD PTR DS:[<&MSVCRT._itoa>] ; char * __cdecl itoa(int, char *, int); 00401649 83C4 0C ADD ESP,0C ; 由于遵守的_cdecl约定因此必须由调用者恢复堆栈[0*4=0xC] 0040164C 8D55 F8 LEA EDX,DWORD PTR SS:[EBP-8] ; 取字符数组snum首地址到EDX {char snum[5];} 0040164F 8BCE MOV ECX,ESI ; 将当前对象的地址在此放回ECX[因为即将调用当前对象的成员函数,调用类的成员函数必须传递对象的地址到ECX寄存器] 00401651 6A 00 PUSH 0 ; 开始传递参数,第三个参数入栈 00401653 6A 00 PUSH 0 ; 开始传递参数,第二个参数入栈 00401655 52 PUSH EDX ; 开始传递参数,第一个参数入栈[要显示的字符串的首地址] 00401656 E8 45020000 CALL <JMP.&MFC42.#4224_?MessageBoxA@CWnd@@QAEHPBD0I@Z> ; int CWnd::MessageBox( LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK ); 0040165B 5E POP ESI ; 恢复ESI 0040165C 5B POP EBX ; 恢复EBX 0040165D 8BE5 MOV ESP,EBP ; 恢复ESP 0040165F 5D POP EBP ; 恢复EBP 00401660 C3 RETN ; 方法返回 00401661 6A 00 PUSH 0 ; 开始传递参数,第四个参数入栈 00401663 6A 00 PUSH 0 ; 开始传递参数,第三个参数入栈 00401665 68 40304000 PUSH Iterator.00403040 ; 开始传递参数,第二个参数入栈 0040166A 6A 00 PUSH 0 ; 开始传递参数,第一个参数入栈 0040166C FF15 C0214000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>] ; USER32.MessageBoxA WINAPI 00401672 5E POP ESI ; 恢复ESI 00401673 5B POP EBX ; 恢复EBX 00401674 8BE5 MOV ESP,EBP ; 恢复ESP 00401676 5D POP EBP ; 恢复EBP 00401677 C3 RETN ; 方法返回   

 

 

 根据分析我们编写一下函数:

void CIteratorDlg::OnBtnFind() { // TODO: Add your control notification handler code here //const int * pnum = find(nums,nums+8,(int)GetDlgItemInt(IDC_EDIT_FINDVALUE));//查询数组 //const int * pnum = find(&nums_vec[0],&nums_vec[nums_vec.size()],(int)GetDlgItemInt(IDC_EDIT_FINDVALUE));//查询vector const int * pnum = find(nums_vec.begin(),nums_vec.end(),(int)GetDlgItemInt(IDC_EDIT_FINDVALUE));//查询vector if (pnum)//如果找到 { char snum[10]; ::itoa(*pnum,snum,10);//转换成字符串 void *p1 =::MessageBox; //取WINAPI函数MessageBox的指针 func p2 = (func)MessageBox; //取CWnd的成员函数MessageBox的指针 //call p1 // _asm // { // push MB_OK //传递第四个参数 // push NULL //传递第三个参数 // lea eax,snum //取字符数组首地址 // push eax //传递第二个参数 // push NULL //传递第一个参数 // call p1 //调用函数 // } //call p2 __asm { push MB_OK //传递第三个参数 push NULL //传递第二个参数 lea eax,snum //取字符数组首地址 push eax //传递第一个参数 mov ecx, this //传递当前对象的地址到ecx[注意:这是调用类的成员函数必须的步骤] call p2 //调用成员函数 } } else { AfxMessageBox("没有找到这个数"); } }

 

你可能感兴趣的:(内联汇编调用WINAPI函数调用类函数)