1. 程式人生 > >C++中使用_asm彙編呼叫動態庫函式的一點問題

C++中使用_asm彙編呼叫動態庫函式的一點問題

    因為從事dll 編寫的相關工作。沒寫完一個dll 之後都要對函式進行測試,對每個dll都要寫一個測試demo的話就非常費勁。能不能一個公共的測試軟體來各種dll裡的函式測試呢?

    嘗試開始,從外界的.h檔案中讀取函式名很簡單,但是我們不能在程式已經編譯的過程中再進行新增定義該 函式的指標。

    比如我dll中有一個

int  add(int a,int b);
     從.h中也讀到了add,然而 沒法再在執行中對其進行如下的定義了,必須開始就定義好。
typedef int (CALLBACK* Fun_add)(int a,int b);
     於是,我們只能從另一種路線入手,通過記憶體地址去查詢這個函式,然後利用匯編向 壓棧引數,然後得到結果。

     例如  我們建立一個ADDdll.dll的動態庫,其中有以下函式。

int __stdcall addabc(int a ,int b,int c)
{
	int sum = a + b + c;
	return  sum;
}

在呼叫該函式的exe 中,我們進行如下操作。
 HINSTANCE hInstLibrary  = LoadLibrary(_T("ADDdll.dll"));
	   if( hInstLibrary == NULL)
	   {
		   MessageBox(NULL,_T("動態庫載入失敗"),NULL,MB_OK);	   
           }
	   else 
	   {
		   MessageBox(NULL,_T("動態庫載入成功"),NULL,MB_OK);
		   int a = 2,b = 3,c = 4;
		   int addstr =(int) GetProcAddress(hInstLibrary,"addabc");//獲得函式的地址
		   if(addstr == 0)
		   {
			   MessageBox(NULL,_T("函式載入失敗"),NULL,MB_OK);
			   goto RE;
		   }
		   else
		   {
                           //為了檢視函式地址具體值得無聊操作,請無視編碼轉化這種坑
                          char bb[50] = {0};
			   sprintf_s(bb,"%x",addstr);
                          WCHAR wszClassName[256];  
			   memset(wszClassName,0,sizeof(wszClassName));  
			   MultiByteToWideChar(CP_ACP,0,bb,strlen(bb)+1,wszClassName,  
				   sizeof(wszClassName)/sizeof(wszClassName[0]));  

			   MessageBox(NULL,wszClassName,NULL,MB_OK);
                           //---------------------------------------------------------
                          int result = 0 ;//用來取結果
			   _asm
			   {
				   push c
				   push b
				   push a //對三個引數壓棧
				   call addstr//召喚這個等食的函式

				   mov dword ptr [result],eax //取回結果,一般函式結果都在eax中。

                          }

			   //★★★add esp,12   前期push的3個int  是12個位元組,C++ 編譯器自己進行了ret 8 真是吊
			   
                           //對取得的結果進行格式化輸出。
                           memset(bb,0,sizeof(bb));
			   sprintf_s(bb,"%d",result);		 
			   memset(wszClassName,0,sizeof(wszClassName));  
			   MultiByteToWideChar(CP_ACP,0,bb,strlen(bb)+1,wszClassName,  
				   sizeof(wszClassName)/sizeof(wszClassName[0]));  

			   MessageBox(NULL,wszClassName,NULL,MB_OK);

		   }
              }
       return TRUE;

RE:
   return FALSE;

   請注意程式碼註釋中的★★★處,當我跟蹤彙編的呼叫動態庫的函式過程中,pull出棧時,指標要加上三個引數之前所佔用的空間。然而這個操作,C++編譯器自己已經進行了操作,開始加那句add時錯的一塌糊塗。。。希望這個小建議能幫大家不繞遠路。

   至於測試工具,就是文書處理歸類的工作了,是上邊那段程式碼的擴充套件了。