因爲C++函數調用多種多樣,本文將分幾個章節分別講解。 app
首先來最簡單的一個無參數調用。 函數
有以下測試代碼: 測試
void func(){ //do nothing here } int main(int argc,char *argv[]) { //call func func(); return 0; }在主函數中調用自定義func函數。
再看看兩個函數的彙編碼: 編碼
void func(){ //顯然和以前講過的main的實現雷同,挖一個192字節棧空間,而後填int 3中斷(清cc) 002F13A0 push ebp 002F13A1 mov ebp,esp 002F13A3 sub esp,0C0h 002F13A9 push ebx 002F13AA push esi 002F13AB push edi 002F13AC lea edi,[ebp+FFFFFF40h] 002F13B2 mov ecx,30h 002F13B7 mov eax,0CCCCCCCCh 002F13BC rep stos dword ptr es:[edi] //do nothing here } 002F13BE pop edi 002F13BF pop esi 002F13C0 pop ebx 002F13C1 mov esp,ebp 002F13C3 pop ebp 002F13C4 ret --- 無源文件 ----------------------------------------------------------------------- 002F13C5 int 3 002F13C6 int 3 002F13C7 int 3 002F13C8 int 3 002F13C9 int 3 002F13CA int 3 002F13CB int 3 002F13CC int 3 002F13CD int 3 002F13CE int 3 002F13CF int 3 --- f:\cpp\clr\consoleapplication1\源.cpp --------------------------------------- int main(int argc,char *argv[]) { 002F13D0 push ebp 002F13D1 mov ebp,esp 002F13D3 sub esp,0C0h 002F13D9 push ebx 002F13DA push esi 002F13DB push edi 002F13DC lea edi,[ebp+FFFFFF40h] 002F13E2 mov ecx,30h 002F13E7 mov eax,0CCCCCCCCh 002F13EC rep stos dword ptr es:[edi] //call func func(); //這裏就編譯出一條指令 call 002F11D1 這個地址是什麼呢,在上面比較遠的地方,爲了簡化,我只取一部分彙編碼: ################################## _GetLastError@0: 002F11BD jmp 002F3972 _RTC_GetErrorFunc: 002F11C2 jmp 002F1980 _wcscpy_s: 002F11C7 jmp 002F391E @_RTC_AllocaHelper@12: 002F11CC jmp 002F1410 func: 002F11D1 jmp 002F13A0 ###002F11D1在這裏 @_RTC_CheckStackVars@8: 002F11D6 jmp 002F1820 @_RTC_CheckStackVars2@12: 002F11DB jmp 002F39D0 __RTC_CheckEsp: ################################## //顯然上面call的是一個跳轉表裏面的func的調轉地址,而不是直接call 002F13A0(真正地址) 002F13EE call 002F11D1 return 0; 002F13F3 xor eax,eax } 002F13F5 pop edi 002F13F6 pop esi 002F13F7 pop ebx 002F13F8 add esp,0C0h 002F13FE cmp ebp,esp 002F1400 call 002F11E0 002F1405 mov esp,ebp 002F1407 pop ebp 002F1408 ret
C++編譯時,把函數地址放到一個跳轉表裏面,調用函數時,去找跳轉表對應函數地址,而後再jmp一次。 spa
能夠看到,調用函數須要跳兩次,同時,會產生許多指令進行棧操做,無論怎樣,調用一個函數必須付出192字節(本例中)代價,無論你有沒有使用局部變量。因此儘可能避免調用過多無心義的函數。 code