天天看點

函數調用原理研究(不用傳遞參數的函數調用)

函數如何調用,在hello world中已經研究過

現在看看一個例子,如何在不傳遞參數的情況下,對變量進行操作

首先對一個c小代碼進行彙編研究

#include <iostream>
using namespace std; 
void print()
{

}
int main()
{ 
 int s=1;
 int ss=2;


    print();
    return 0;
}
           

利用vs2008觀察彙編代碼:

int main()
{ 
01361480  push        ebp  
01361481  mov         ebp,esp 
01361483  sub         esp,0D8h 
01361489  push        ebx  
0136148A  push        esi  
0136148B  push        edi  
0136148C  lea         edi,[ebp-0D8h] 
01361492  mov         ecx,36h 
01361497  mov         eax,0CCCCCCCCh 
0136149C  rep stos    dword ptr es:[edi] 
<strong> int s=1;
0136149E  mov         dword ptr [s],1 
 int ss=2;
013614A5  mov         dword ptr [ss],2 </strong>


    print();
013614AC  call        print (13610AFh) 
    return 0;
013614B1  xor         eax,eax 
}
           
void print()
{
<strong>013613C0  push        ebp  
013613C1  mov         ebp,esp </strong>
013613C3  sub         esp,0C0h 
013613C9  push        ebx  
013613CA  push        esi  
013613CB  push        edi  
013613CC  lea         edi,[ebp-0C0h] 
013613D2  mov         ecx,30h 
013613D7  mov         eax,0CCCCCCCCh 
013613DC  rep stos    dword ptr es:[edi] 

}
           

這裡需要了解一個概念,寄存器EBP,

書本了解就是

擴充 基址 指針 寄存器(extended base pointer) 其記憶體放一個指針,該指針指向系統棧最上面一個 棧幀的底部。 簡單而言就是,在函數嵌套調用時,當一個函數傳回時,如何保證還要回到之前的棧位址,就需要EBP這個寄存器,

在進如print時,可以看到頭兩句彙編,就是将上一個函數的棧底壓棧,儲存現場,

如果得到這個棧底位址就可以操作變量了

oid print()
{
	  unsigned int addr;
    __asm{
        mov addr,ebp
    }
    int *p=(int *)(*(int *)addr-8);

        cout<<*p<<endl;
}
           

看看vs單步調試的一些資訊

函數調用原理研究(不用傳遞參數的函數調用)

再看看print函數中師傅捕獲到這個EBP

函數調用原理研究(不用傳遞參數的函數調用)

通過這樣應該明白這種方法的原理了