【彙編】C++ 函數調用分析之——無參調用。

因爲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

相關文章
相關標籤/搜索