• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            兔子的技術博客

            兔子

               :: 首頁 :: 聯系 :: 聚合  :: 管理
              202 Posts :: 0 Stories :: 43 Comments :: 0 Trackbacks

            留言簿(10)

            最新評論

            閱讀排行榜

            評論排行榜

                   現代的編程語言的函數竟然有那麼多的調用方式。這些東西要完全理解還得通過匯編代碼才好理解。他們各自有自己的特點
            其實這些調用方式的差別在主要在一下幾個方面

            1.參數處理方式(傳遞順序,存取(利用盞還是寄存器))
            2.函數的結尾處理方式(善后處理)



            以下是理論:
            __cdecl    由調用者平棧,參數從右到左依次入棧 是C和C++程序的缺省調用方式。每一個調用它的函數都包含清空堆棧的代碼
            所以產生的可執行文件大小會比調用_stdcall函數的大。函數采用從右到左的壓棧方式。VC將函數編譯后會在函數名前面加上
            下劃線前綴。是MFC缺省調用約定
            __stdcall ,WINAPI,CALLBACK ,PASCAL 由被調用者平棧,參數從右到左依次入棧 ._stdcall是Pascal程序的缺省調用方式,
            通常用于Win32   Api中,函數采用從右到左的壓棧方式,自己在退出時清空堆棧。VC將函數編譯后會在函數名前面加上下劃
            線前綴,在函數名后加上"@"和參數的字節數

            __fastcall 由被調用者平棧,參數先賦值給寄存器,然后入棧 “人”如其名,它的主要特點就是快,因為它是通過寄存器來傳送參數的
            (實際上,它用ECX和EDX傳送前兩個雙字(DWORD)或更小的參數,剩下的參數仍舊自右向左壓棧傳送,被調用的函數在返回前
            清理傳送參數的內存棧),在函數名修飾約定方面,它和前兩者均不同.
            _fastcall方式的函數采用寄存器傳遞參數,VC將函數編譯后會在函數名前面加上"@"前綴,在函數名后加上"@"和參數的字節數。 

            __thiscall 由被調用者平棧,參數入棧,this 指針賦給 ecx 寄存器 僅僅應用于“C++”成員函數。this指針存放于CX寄存器,參數從右
            到左壓。thiscall不是關鍵詞,因此不能被程序員指定。  


            __declspec(naked) 這是一個很少見的調用約定,一般程序設計者建議不要使用。編譯器不會給這種函數增加初始化和清理代碼
            更特殊的是,你不能用return返回返回值,只能用插入匯編返回結果。這一般用于實模式驅動程序設計.
            以下是實踐:

              
            int __stdcall test_stdcall(char para1, char para2)
            {
                para1 
            = para2;
                
            return 0;
            }
            int __cdecl test_cdecl(char para, )
            {
                
            char    p = '\n';
                va_list marker;
                va_start( marker, para );
                
            while( p != '\0' )
                {
                    p 
            = va_arg( marker, char);
                    printf(
            "%c\n", p);
                }
                va_end( marker );
                
            return 0;
            }

            int pascal test_pascal(char para1, char para2)
            {
                
            return 0;
            }

            int __fastcall test_fastcall(char para1, char para2, char para3, char para4)
            {
                para1 
            = (char)1;
                para2 
            = (char)2;
                para3 
            = (char)3;
                para4 
            = (char)4;
                
            return 0;
            }
            __declspec(naked) 
            void __stdcall test_naked(char para1, char para2)
            {
                __asm
                {
                    push    ebp
                    mov     ebp, esp
                    push    eax
                    mov     al,
            byte ptr [ebp + 0Ch]
                    xchg    
            byte ptr [ebp + 8],al      
                    pop     eax
                    pop     ebp
                    ret     
            8
                }
            //    return ;
            }


            int main(int argc, char* argv[])
            {
                test_stdcall( 
            'a''b' );
                test_cdecl( 
            'c','d','e','f','g' ,'h' ,'\0');
                test_pascal( 
            'e''f' );
                test_fastcall( 
            'g''h''i''j' );
                test_naked( 
            'k''l');
                
            return 0;
            }
            匯編代碼如下
            int main(int argc, char* argv[])
            {
            00411350  push        ebp  
            00411351  mov         ebp,esp 
            00411353  sub         esp,0C0h 
            00411359  push        ebx  
            0041135A  push        esi  
            0041135B  push        edi  
            0041135C  lea         edi,[ebp
            -0C0h] 
            00411362  mov         ecx,30h 
            00411367  mov         eax,0CCCCCCCCh 
            0041136C  rep stos    dword ptr es:[edi] 
                test_stdcall( 
            'a''b' );
            0041136E  push        62h  
            00411370  push        61h  
            00411372  call        
            _test_stdcall@8

                test_cdecl( 
            'c','d','e','f','g' ,'h' ,'\0');
            00411377  push        0    
            00411379  push        68h  
            0041137B  push        67h  
            0041137D  push        66h  
            0041137F  push        65h  
            00411381  push        64h  
            00411383  push        63h  
            00411385  call        _test_cdecl

            0041138A  add         esp,1Ch 
            ;恢復_test_cdecl參數壓入前的堆棧指令是: add esp,n*4 n=參數的數量
                test_fastcall( 'g''h''i''j' );
            0041138D  push        6Ah  
            0041138F  push        69h  
            00411391  mov         dl,68h 
            00411393  mov         cl,67h 
            00411395  call        test_fastcall

                test_naked( 
            'k''l');
            0041139A  push        6Ch  
            0041139C  push        6Bh  
            0041139E  call        
            _test_naked
                
            return 0;
            004113A3  xor         eax,eax 
            }

            int __stdcall test_stdcall(char para1, char para2)
            {
            004111F0  push        ebp  
            004111F1  mov         ebp,esp 
            004111F3  sub         esp,0C0h 
            004111F9  push        ebx  
            004111FA  push        esi  
            004111FB  push        edi  
            004111FC  lea         edi,[ebp-0C0h] 
            00411202  mov         ecx,30h 
            00411207  mov         eax,0CCCCCCCCh 
            0041120C  rep stos    dword ptr es:[edi] ;初始edi
                para1 = para2;
            0041120E  mov         al,byte ptr [para2] ;mov al,byte ptr[ebp+c]
            00411211  mov         byte ptr [para1],al ;mov byte ptr[ebp+8],al

                return 0;
            00411214  xor         eax,eax
            00411216  pop         edi  
            00411217  pop         esi  
            00411218  pop         ebx  
            00411219  mov         esp,ebp 
            0041121B  pop         ebp  
            0041121C ret      8 ;恢復到壓入函數參數前堆棧,由于有兩個參數所以ret 8 相當于 pop eip 然后esp+8
            }
            int __cdecl test_cdecl(char para,... )
            {
            00411230  push        ebp  
            00411231  mov         ebp,esp 
            00411233  sub         esp,0D8h 
            0041123C  lea         edi,[ebp-0D8h] 
            00411242  mov         ecx,36h 
            00411247  mov         eax,0CCCCCCCCh 
            0041124C  rep stos    dword ptr es:[edi] 
                char    p = '\n';
            0041124E  mov         byte ptr [p],0Ah 
                va_list marker;
                va_start( marker, para );
            00411252  lea         eax,[ebp+0Ch] 
            00411255  mov         dword ptr [marker],eax 
                while( p != '\0' )
            00411258  movsx       eax,byte ptr [p] 
            0041125C  test        eax,eax 
            0041125E  je          test_cdecl+60h (411290h) 
                {
                    p = va_arg( marker, char);
            00411260  mov         eax,dword ptr [marker] 
            00411263  add         eax,4 
            00411266  mov         dword ptr [marker],eax 
            00411269  mov         ecx,dword ptr [marker] 
            0041126C  mov         dl,byte ptr [ecx-4] 
            0041126F  mov         byte ptr [p],dl 
                    printf("%c\n", p);
            00411272  movsx       eax,byte ptr [p] 
            00411276  mov         esi,esp 
            00411278  push        eax  
            00411279  push        offset string "%c\n" (41401Ch) 
            0041127E  call        dword ptr [__imp__printf (416180h)] 
            00411284  add         esp,8 
            0041128E  jmp         test_cdecl+28h (411258h) 
                }
                va_end( marker );
            00411290  mov         dword ptr [marker],0 
                return 0;
            00411297  xor         eax,eax 

            004112A9  mov         esp,ebp 
            004112AB  pop         ebp  
            004112AC  ret    

            }
                 
            int __fastcall test_fastcall(char para1, char para2, char para3, char para4)
            {
            004112D0  push        ebp  
            004112D1  mov         ebp,esp 
            004112D3  sub         esp,0D8h  
            004112DD  lea         edi,[ebp-0D8h] 
            004112E3  mov         ecx,36h 
            004112E8  mov         eax,0CCCCCCCCh 
            004112ED  rep stos    dword ptr es:[edi] 
            004112EF  pop         ecx  
            004112F0  mov         byte ptr [ebp-14h],dl 
            004112F3  mov         byte ptr [ebp-8],cl 
                para1 = (char)1;
            004112F6  mov         byte ptr [para1],1 
                para2 = (char)2;
            004112FA  mov         byte ptr [para2],2 
                para3 = (char)3;
            004112FE  mov         byte ptr [para3],3 
                para4 = (char)4;
            00411302  mov         byte ptr [para4],4 
                return 0;
            00411306  xor         eax,eax  

            0041130B  mov         esp,ebp 
            0041130D  pop         ebp  
            0041130E  ret         8  
            ;由于使用了ecx ,edx 傳遞參數 本來4個參數只使用兩push 所以這里是 ret 4*2
            }
                 

            __declspec(naked) void __stdcall test_naked(char para1, char para2)
            {
            00411330  push        ebp      ;這里編譯器沒加入任何初始化和清棧的指令,你代碼如何寫它就復制過來
            00411331  mov         ebp,esp 
            00411333  push        eax  
            00411334  mov         al,byte ptr [para2]    
            00411337  xchg        al,byte ptr [para1] 
            0041133A  pop         eax  
            0041133B  pop         ebp  
            0041133C  ret         8  

            posted on 2010-07-02 14:07 會飛的兔子 閱讀(649) 評論(0)  編輯 收藏 引用 所屬分類: C++庫,組件系統API,底層技術
            久久精品综合网| 91久久婷婷国产综合精品青草| 日产精品99久久久久久| 亚洲国产精品久久66| 国内精品人妻无码久久久影院| 久久妇女高潮几次MBA| 精品熟女少妇AV免费久久| 久久久久波多野结衣高潮| 久久无码AV中文出轨人妻| 久久精品成人影院| 狠狠久久综合伊人不卡| 久久久久久国产精品免费免费| 99久久精品免费国产大片| 国产亚洲精午夜久久久久久| 久久这里只有精品18| 精品久久久久久无码中文字幕| 久久精品国产亚洲综合色| 97热久久免费频精品99| 国产一久久香蕉国产线看观看| 久久精品国产久精国产| 久久久久亚洲AV成人网人人网站| 午夜精品久久久久久影视777 | 狠狠色噜噜狠狠狠狠狠色综合久久| 无码人妻精品一区二区三区久久久| 久久精品国产亚洲av麻豆色欲| 久久国产精品国产自线拍免费| 国产三级精品久久| 日韩欧美亚洲综合久久影院Ds | 久久最近最新中文字幕大全| 久久精品国产福利国产琪琪| 色天使久久综合网天天| 国产精品久久久久久福利漫画| 狠狠色伊人久久精品综合网| 国产精品99久久久精品无码| 久久久一本精品99久久精品66| 国内精品久久久久久久亚洲| 久久中文字幕人妻丝袜| 麻豆精品久久久一区二区| 欧美亚洲国产精品久久| 亚洲国产成人久久精品影视| 久久久久亚洲AV无码专区首JN|