naked 函數調用

來源:互聯網
上載者:User

正常的情況下,我們寫一個 C/C++ 函數,即使是一個空函數,編譯器也為我們做了不少的工作,產生了一些“必要”的代碼。請看下面的函數 (為了說明問題隨便寫的): 
int Test() {      int iReturn;     char szTemp[33];          szTemp[0] = 'A';     szTemp[1] = '';     iReturn = MessageBox(NULL, szTemp, szTemp, MB_OK);     MessageBeep(iReturn);     return iReturn;  }

下面是用 VC6 在 Release 方式下編譯後的的反組譯碼代碼:

00401000   sub         esp,24h     // 增加堆棧空間存放局部變數 (24H = 36D,4 位元組對齊,注意這裡沒有為 iReturn 分配空間)
 00401003   push        esi         // 儲存要使用的重要寄存器
 00401004   lea         eax,[esp+4] // 下面是傳遞 MessageBox() 要使用的參數
 00401008   push        0
 0040100A   lea         ecx,[esp+8] // 編譯器愚蠢,根本不用 ECX,兩個都是 szTemp,兩次 PUSH EAX 不得了
 0040100E   push        eax
 0040100F   push        ecx
 00401010   push        0
 00401012   mov         byte ptr [esp+14h],41h
 00401017   mov         byte ptr [esp+15h],0
 0040101C   call        dword ptr ds:[40509Ch] // 調用 MessageBox()
 00401022   mov         esi,eax     // 儲存傳回值到變數 iReturn 。靠!變數 iReturn 自動使用 ESI,編譯器太聰明了:)
 00401024   push        esi
 00401025   call        dword ptr ds:[4050A0h] // 調用 MessageBeep()
 0040102B   mov         eax,esi     // 把變數 iReturn 交給 EAX 作為傳回值
 0040102D   pop         esi         // 恢複要使用的重要寄存器
 0040102E   add         esp,24h     // 減少堆棧空間
 00401031   ret                     // 堆棧長度減 4 並返回

這段代碼雖然很精幹 (都能自動使用寄存器來儲存變數了),但是有的時候我們並不需要編譯器提供這些自作主張的代碼 (比如寫驅動程式的時候,不過我還沒遇到過這種情況,呵呵~~),我們希望整個全部函數都是自己親手寫進去的 (BT 呀^o^)。好,請出今天的主角 —— “naked”(怎麼是裸體呀?),歡迎!Visual C++ 的擴充關鍵字 naked 允許我們完全定製一個函數,廢話不說了,看例子 (熬夜寫的 Zzzzzz~~):

__declspec(naked) int Test() {      __asm     {          SUB         ESP,24H
         PUSH        ESI
         LEA         EAX,[ESP+4]
         PUSH        0                      
         PUSH        EAX                    
         PUSH        EAX                    
         PUSH        0                      
         MOV         BYTE PTR [ESP+14H],41H 
         MOV         BYTE PTR [ESP+15H],0   
         CALL        DWORD PTR [MessageBoxA] 
         MOV         ESI,EAX
         PUSH        ESI                    
         CALL        DWORD PTR [MessageBeep] 
         MOV         EAX,ESI
         POP         ESI
         ADD         ESP,24H
         RET
      }  }

上面的代碼是使用的 VC 的內聯彙編,和 VC 編譯後產生的程式碼完全是一樣的 (很有完全控制的成就感吧^_^)。上面我們並沒有又節省什麼 (節省的 PUSH ECX 並不是 naked 的功勞),但是有的時候確實需要的 (舉不出例子來了,倒!)。最後隨便說說注意事項: 

1.使用 naked 關鍵字需要自己構建 EBP 參數指標 (如果用到了 EBP 作為參數指標的話);
2.必須自己使用 RET 或 RET n 指令返回 (除非你不返回)。
3.只有win32模式能用__asm ipf和和x64模式不能嵌入內聯彙編。沒什麼特殊情況還是用intrinsic吧

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.