您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關怎樣進行C++調用,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
進行C++調用時遇到了棘手的問題,Naked Call這是一個很少見的C++調用約定,建議程序設計者不要使用。編譯器不會給這種函數增加初始化和清理代碼,省的變成了白用工。
調用處push 1push 2call functionadd esp,8 注意:這里C++調用者在恢復堆棧被調用函數_function處push ebp 保存ebp寄存器,該寄存器將用來保存堆棧的棧頂指針,可以在函數退出時恢復mov ebp,esp 保存堆棧指針mov eax,[ebp + 8H] 堆棧中ebp指向位置之前依次保存有ebp,cs:eip,a,b,ebp +8指向aadd eax,[ebp + 0CH] 堆棧中ebp + 12處保存了bmov esp,ebp 恢復esppop ebpret 注意,這里沒有修改堆棧
MSDN中說,該修飾自動在函數名前加前導的下劃線,因此函數名在符號表中被記錄為_function,但是我在編譯時似乎沒有看到這種變化。由于參數按照從右向左順序壓棧,因此最開始的參數在最接近棧頂的位置,因此當采用不定個數參數時,***個參數在棧中的位置肯定能知道,只要不定的參數個數能夠根據***個后者后續的明確的參數確定下來,就可以使用不定參數,例如對于CRT中的sprintf函數,定義為:
class A{public: int function1(int a,int b); int function2(int a,...);}; int A::function1 (int a,int b){ return a+b; }#include int A::function2(int a,...) { va_list ap; va_start(ap,a); int i; int result = 0; for(i = 0 ; i < a ; i ++) { result += va_arg(ap,int); }
函數的***個和第二個DWORD參數(或者尺寸更小的)通過ecx和edx傳遞,其他參數通過從右向左的順序壓棧被調用函數清理堆棧函數名修改規則同這是一個很少見的調用約定,一般程序設計者建議不要使用。
編譯器不會給這種函數增加初始化和清理代碼,更特殊的是,你不能用return返回返回值,只能用插入匯編返回結果。這一般用于實模式驅動程序設計,假設定義一個求和的加法程序,可以定義為:
__declspec(naked) int add(int a,int b){ __asm mov eax,a __asm add eax,b __asm ret }
注意,這個函數沒有顯式的return返回值,返回通過修改eax寄存器實現,而且連退出函數的ret指令都必須顯式插入。上面代碼被翻譯成匯編以后變成:
declspec(naked) int add(int a,int b){ __asm mov eax,a __asm add eax,b __asm ret }
由于調用者沒有理解WINAPI的含義錯誤的增加了這個修飾,上述代碼必然導致堆棧被破壞,MFC在編譯時插入的checkesp函數將告訴你,堆棧被破壞了。
以上就是怎樣進行C++調用,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。