隨想錄(由自訂列印函數想到的)

來源:互聯網
上載者:User

【 聲明:著作權,歡迎轉載,請勿用於商業用途。  聯絡信箱:feixiaoxing @163.com】


        在編寫代碼的時候我們都會自己重新定義一個列印函數,為什麼要這樣呢?我想主要原因還是為了定義其中的列印開關。如果開啟了開關,我們當然可以看到很多的列印資訊,但是如果不需要這些資訊,我們就可以關上這些開關,所以一般的列印函數函數都是可以自己定義的。

#include <stdio.h>#include <windows.h>void XiaoxingPrintf(char* str, ...){char buffer[64];va_list va;va_start(va, str);vsprintf(buffer, str, va);va_end(va);printf("%s\n", buffer);}int main(int argc, char* argv[]){XiaoxingPrintf(" argc = %d, &argv = 0x%x\n", argc, &argc);return 1;}

        上面的這段代碼其實也很平常,看上去沒有什麼特別之處,但是我們想知道,這個va究竟是個什麼東西?不妨可以反組譯碼看一下,

7:    void XiaoxingPrintf(char* str, ...)8:    {0040D430   push        ebp0040D431   mov         ebp,esp0040D433   sub         esp,84h0040D439   push        ebx0040D43A   push        esi0040D43B   push        edi0040D43C   lea         edi,[ebp-84h]0040D442   mov         ecx,21h0040D447   mov         eax,0CCCCCCCCh0040D44C   rep stos    dword ptr [edi]9:        char buffer[64];10:       va_list va;11:12:       va_start(va, str);0040D44E   lea         eax,[ebp+0Ch]0040D451   mov         dword ptr [ebp-44h],eax13:       vsprintf(buffer, str, va);0040D454   mov         ecx,dword ptr [ebp-44h]0040D457   push        ecx0040D458   mov         edx,dword ptr [ebp+8]0040D45B   push        edx0040D45C   lea         eax,[ebp-40h]0040D45F   push        eax0040D460   call        vsprintf (0040d750)0040D465   add         esp,0Ch14:       va_end(va);0040D468   mov         dword ptr [ebp-44h],015:16:       printf("%s\n", buffer);0040D46F   lea         ecx,[ebp-40h]0040D472   push        ecx0040D473   push        offset string "%s\n" (0042201c)0040D478   call        printf (0040d850)0040D47D   add         esp,817:   }0040D480   pop         edi0040D481   pop         esi0040D482   pop         ebx0040D483   add         esp,84h0040D489   cmp         ebp,esp0040D48B   call        __chkesp (0040d710)0040D490   mov         esp,ebp0040D492   pop         ebp0040D493   ret

        上面的彙編代碼很多,其實有用的資訊並不多。首先我們看va_start這一句話,好像做的事情很簡單,就是把ebp+0xc給了va,va本身佔用了四個位元組,也就是位於[ebp-44h]的位置。那麼最後的va_end呢,也不複雜,也就是把[ebp-44h]的位置清零了一下。但是可慮到這裡的va是一個臨時變數,是否清零其實意義不大。那麼,這裡的ebp+0xc是什麼意思呢?首先我們看到,ebp上面的數值是原來push
ebp的數值,ebp+4是函數的返回地址,ebp+8是str的地址,那麼很明顯,ebp+0xc就是第二個參數的地址。所以,我們可以對這個列印函數稍微改造一下,

void XiaoxingPrintf(char* str, ...){char buffer[64];vsprintf(buffer, str, &str + 1);printf("%s\n", buffer);}

        同樣一個函數,三句話就可以搞定了。不再需要記住那麼多標頭檔和資料類型。當然,這背後需要你對函數堆棧、參數地址、ebp和esp理解得比較深刻和具體了。



聯繫我們

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