C++反組譯碼第一講,認識建構函式,解構函式,以及成員函數

來源:互聯網
上載者:User

標籤:this指標   改變   局部變數   getch   get   根據   font   cal   圖片   

          C++反組譯碼第一講,認識建構函式,解構函式,以及成員函數

以前說過在C系列下的彙編,怎麼認識函數.那麼現在是C++了,隱含有構造和解構函式

 

 

一丶認識建構函式

進階代碼:

  

class MyTest{public:    MyTest();    ~MyTest();public:    DWORD m_dwTest;}; MyTest::MyTest() {     printf("1111\r\n");        //構造的時候先列印      } MyTest::~MyTest() {    printf("2222\r\n");        //析構的時候列印 }int main(int argc, char* argv[]){    MyTest Test;              //建立局部對象    getchar();    return 0;}

C++中的類,構造的時候先祖先類,然後父類,最後朋友類,然後在構造自己.  析構的時候 先自己 後朋友 接著父類 然後是祖先類,(明白一下順序)

Debug下的彙編代碼

  

這個是main函數內部,在建立對象的時候,會先調用構造,然後退出的時候會調用析構(上面是我改名字過後的)

現在我們認識構造有幾個必要條件

1.ecx,this傳參因為C++下的對象都是 thisCall,和FastCall類似,thisCall會通過寄存器傳參.而fastCall最後兩個參數會通過寄存器傳參.

.評鑑是ecx傳參的前提下是函數外面給值,函數內部使用

函數內部會將ecx給儲存起來,這個記憶體空間稱之為  this,也就是文法為什麼可以這樣寫: this.xxxx = 1  this.MyTest();

高亮ecx傳參的時候的記憶體位址,會有多處使用. 

2.構造會在建立對象的時候先調用

3.建構函式的傳回值則是this指標.

詳解怎麼查看建構函式

1.是ecx傳參,確定了一個條件,其餘兩個條件還沒有滿足

2.函數內部使用ecx,且給this指標賦值,並且返回了this指標

返回的彙編: 

3.該函數是當前棧範圍下的第一次調用

  

main函數中初始化成員變數為ccc之後,調用的第一個.

PS: 附加條件 我們點擊ecx傳參的時候的局部變數(this)會有多處使用.

一般來說確定上面三點則可以確定是建構函式了.上面三個都是必要條件.

而充分條件以後學習虛表的時候就知道了,構造會初始化虛表,且是第一個,所以可以直接確定是建構函式了.

 

說的聽過,其實看反組譯碼代碼也就3 - 4秒的事情.

Release下的彙編

根據上面代碼,可以確定

1.先調用的第一個函數

2.ecx傳參.並且內部使用了ecx,賦值給了this指標,且把this指標返回

 

 注意:建構函式,解構函式只能是thiscall,就算你自己加上呼叫慣例,編譯的時候也提示是無效的呼叫慣例,且反組譯碼代碼不會做任何改變.

總結:

  1.建構函式優先調用

  2.ecx傳參,且函數內部會將ecx給this賦值(this可能是一塊記憶體空間,也可能是寄存器變數)且返回this指標

  3.可以點擊this指標,可能會有多次調用

注: 構造析構都是thiscall,不能修改

 

 二丶識別解構函式

識別解構函式和建構函式類似

1.thiscall,並且最後調用

2.無傳回值

看下解構函式

1.最後一次調用的

  

2.thiscall,無傳回值,其內部會使用ecx給this賦值

 

  

 Release下的彙編和Debug下一樣,有最佳化,可能你不使用this則不會給this賦值.但是還是無傳回值

 總結:

  1.析構最後一次調用

  2.thiscall傳參

  3.無傳回值

三丶識別成員函數(c call  thiscall  fastcall  stdcall)

進階代碼:

  

class MyTest{public:    MyTest();    ~MyTest();    void SetTest(DWORD dwTest);    DWORD GetTest();public:    DWORD m_dwTest;}; MyTest::MyTest() {     printf("1111\r\n");      } MyTest::~MyTest() {    printf("2222\r\n"); }void MyTest::SetTest(DWORD dwTest){    this->m_dwTest = dwTest;   }DWORD MyTest::GetTest(){    return this->m_dwTest;}int main(int argc, char* argv[]){    MyTest Test;    Test.SetTest(1);          int Number = Test.GetTest();      //添加了Set,Get方法,並調用    getchar();    return 0;}

看上面,我們可以看出都是預設的thiscall,看下反組譯碼代碼 (看各種呼叫慣例會產生什麼樣的結果)

1.預設的thiscall在彙編中的表現形式

Debug下的反組譯碼

頭尾是構造和析構,中間則是我們的SetGet方法,可以看出,如果是thiscall,那麼是ecx傳參,且裡面ecx會給this指標賦值,且返回this指標

Release和Debug類似,可能有少許最佳化,為了篇幅原因,不在. 

2.Stdcall 成員函數表現形式

看上面彙編代碼得出

1.this指標是  ebp + var_10,

2.在stdcall下,會將this指標給寄存器,然後push進去

總結:

  1.stdcall 會將this指標當做參數push進去.

  2. push進去的this指標,會在call上面第一個push,也就是說this指標是第一個參數

  3.平棧還是按照stdcall的形式平棧

 

 3.C call下的彙編表現形式

  

也是通過push的方式,將this指標當做參數傳遞

然後c呼叫慣例在外面平棧

4.fastCall的彙編表現形式

 寄存器傳參,然後ecx是外部更改,內部使用

 

最終的大總結:

    1).識別構造

      1.建構函式優先調用

      2.ecx傳參,且函數內部會將ecx給this賦值(this可能是一塊記憶體空間,也可能是寄存器變數)且返回this指標

      3.可以點擊this指標,可能會有多次調用

      注: 構造析構都是thiscall,不能修改

 

    2).識別析構

      1.析構最後一次調用

      2.thiscall傳參

      3.無傳回值

  

    3).識別各種呼叫慣例的成員函數

       1.c呼叫慣例,會將this指標push進去,然後平棧按照c呼叫慣例平棧

       2.stdcall,會將this指標push進去,內部平棧

      3.thiscall會預設使用ecx,外部更改,內部使用,平棧和stdcall一樣

      4.fastcall,會使用兩個寄存器傳參,且也會外部更改ecx,內部使用.

      5.c約定,std約定,push的時候都是this指標,且是第一個參數(也就是call上面的最近的一個push,必定為this指標)

 

   

C++反組譯碼第一講,認識建構函式,解構函式,以及成員函數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.