【汇编】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

相关文章
相关标签/搜索