• <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>

              C++博客 :: 首頁 :: 聯(lián)系 ::  :: 管理
              163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(48)

            我參與的團隊

            搜索

            •  

            積分與排名

            • 積分 - 398977
            • 排名 - 59

            最新評論

            閱讀排行榜

            評論排行榜

            stdcall很多時候被稱為pascal調(diào)用約定,因為pascal是早期很常見的一種教學(xué)用計算機程序設(shè)計語言,其語法嚴謹,使用的函數(shù)調(diào)用約定就是 stdcall。在Microsoft C++系列的C/C++編譯器中,常常用PASCAL宏來聲明這個調(diào)用約定,類似的宏還有WINAPI和 CALLBACK。
            stdcall調(diào)用約定聲明的語法為(以前文的那個函數(shù)為例):
            int __stdcall function(int a,int b)
            stdcall的調(diào)用約定意味著:1)參數(shù)從右向左壓入堆棧,2)函數(shù)自身修改堆棧 3)函數(shù)名自動加前導(dǎo)的下劃線,后面緊跟一個@符號,其后緊跟著參數(shù)的尺寸
            以上述這個函數(shù)為例,參數(shù)b首先被壓棧,然后是參數(shù)a,函數(shù)調(diào)用function(1,2)調(diào)用處翻譯成匯編語言將變成:
            push 2      第二個參數(shù)入棧
            push 1      第一個參數(shù)入棧
            call function  調(diào)用參數(shù),注意此時自動把cs:eip入棧
            而對于函數(shù)自身,則可以翻譯為: 
            push ebp     保存ebp寄存器,該寄存器將用來保存堆棧的棧頂指針,可以在函數(shù)退出時恢復(fù)
            mov ebp,esp  保存堆棧指針
            mov  eax,[ebp + 8H]  堆棧中ebp指向位置之前依次保存有ebp,cs:eip,a,b,ebp +8指向a
            add eax,[ebp + 0CH]  堆棧中ebp + 12處保存了b
            mov  esp,ebp         恢復(fù)esp
            pop ebp
            ret 8
            而在編譯時,這個函數(shù)的名字被翻譯成_function@8 
            注意不同編譯器會插入自己的匯編代碼以提供編譯的通用性,但是大體代碼如此。其中在函數(shù)開始處保留esp到ebp中,在函數(shù)結(jié)束恢復(fù)是編譯器常用的方法。
            從函數(shù)調(diào)用看,2和1依次被push進堆棧,而在函數(shù)中又通過相對于ebp(即剛進函數(shù)時的堆棧指針)的偏移量存取參數(shù)。函數(shù)結(jié)束后,ret 8表示清理8個字節(jié)的堆棧,函數(shù)自己恢復(fù)了堆棧。

            c程序默認的是__cdecl
            __stdcall時輸入?yún)?shù)的棧空間有被調(diào)用函數(shù)恢復(fù)
            __cdecl時由調(diào)用函數(shù)恢復(fù)
            和參數(shù)如棧順序不同,記不清楚了

            是編譯器調(diào)用約定的一種 
            調(diào)用約定分為_cdecl _stdcall _fastcall thiscall naked  call等等 網(wǎng)絡(luò)上很多調(diào)用約定的介紹
             _stdcall將參數(shù)壓棧是按C語言的順序(從右到左),但與C 語言不同的是它是由被調(diào)用者將參數(shù)從棧中清除的,所以它的編譯文件比_cdecl?gt;>stdcall是Windows API函數(shù)中默認的調(diào)用約定,VB、VFP等也采用這個約定。 
               _cdecl是C語言采用的默認調(diào)用方法,它的優(yōu)點是支持printf這樣的可變參數(shù)調(diào)用。 
              另外,VC++對于兩種調(diào)用方法的名稱轉(zhuǎn)換方法也不同
            ++++++++++++++++++++++++++++++++++++++++++++++++++++
            _stdcall  
            按 從右至左的順序壓參數(shù)入棧,由被調(diào)用者把參數(shù)彈出棧。對于“C”函數(shù)或者變量,修飾名以下劃線為前綴,然后是函數(shù)名,然后是符號“@”及參數(shù)的字節(jié)數(shù),如 函數(shù)int  func(int  a,  double  b)的修飾名是_func@12。對于“C++”函數(shù),則有所不同。   
            所有的Win32  API函數(shù)都遵循該約定。  
            +++++++++++++++++++++++++++++++++++++++++++++++++++++

            函數(shù)調(diào)用約定有多種,這里簡單說一下:
            1、__stdcall調(diào)用約定相當(dāng)于16位動態(tài)庫中經(jīng)常使用的PASCAL調(diào)用約定。在32 位的VC++5.0中PASCAL調(diào)用約定不再被支持(實際上它已被定義為__stdcall。除了__pascal外,__fortran和 __syscall也不被支持),取而代之的是__stdcall調(diào)用約定。兩者實質(zhì)上是一致的,即函數(shù)的參數(shù)自右向左通過棧傳遞,被調(diào)用的函數(shù)在返回前 清理傳送參數(shù)的內(nèi)存棧,但不同的是函數(shù)名的修飾部分(關(guān)于函數(shù)名的修飾部分在后面將詳細說明)。
            _stdcall是Pascal程序的缺省調(diào)用方式,通常用于Win32 Api中,函數(shù)采用從右到左的壓棧方式,自己在退出時清空堆棧。VC將函數(shù)編譯后會在函數(shù)名前面加上下劃線前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù)。
            2、C調(diào)用約定(即用__cdecl關(guān)鍵字說明)按從右至左的順序壓參數(shù)入棧,由調(diào)用者把參數(shù)彈出棧。對于傳送參數(shù)的內(nèi)存棧是由調(diào)用者來維護的(正因為如此,實現(xiàn)可變參數(shù)的函數(shù)只能使用該調(diào)用約定)。另外,在函數(shù)名修飾約定方面也有所不同。
            _cdecl是C和C++程序的缺省調(diào)用方式。每一個調(diào)用它的函數(shù)都包含清空堆棧的代碼,所以產(chǎn)生的可執(zhí)行文件大小會比調(diào)用_stdcall函數(shù)的大。函數(shù)采用從右到左的壓棧方式。VC將函數(shù)編譯后會在函數(shù)名前面加上下劃線前綴。是MFC缺省調(diào)用約定。
            3、 __fastcall調(diào)用約定是"人"如其名,它的主要特點就是快,因為它是通過寄存器來傳送參數(shù)的(實際上,它用ECX和EDX傳送前兩個雙字 (DWORD)或更小的參數(shù),剩下的參數(shù)仍舊自右向左壓棧傳送,被調(diào)用的函數(shù)在返回前清理傳送參數(shù)的內(nèi)存棧),在函數(shù)名修飾約定方面,它和前兩者均不同。
            _fastcall方式的函數(shù)采用寄存器傳遞參數(shù),VC將函數(shù)編譯后會在函數(shù)名前面加上"@"前綴,在函數(shù)名后加上"@"和參數(shù)的字節(jié)數(shù)。 
            4、thiscall僅僅應(yīng)用于"C++"成員函數(shù)。this指針存放于CX寄存器,參數(shù)從右到左壓。thiscall不是關(guān)鍵詞,因此不能被程序員指定。
            5、naked call采用1-4的調(diào)用約定時,如果必要的話,進入函數(shù)時編譯器會產(chǎn)生代碼來保存ESI,EDI,EBX,EBP寄存器,退出函數(shù)時則產(chǎn)生代碼恢復(fù)這些寄存器的內(nèi)容。
            naked call不產(chǎn)生這樣的代碼。naked call不是類型修飾符,故必須和_declspec共同使用。
            關(guān) 鍵字 __stdcall、__cdecl和__fastcall可以直接加在要輸出的函數(shù)前,也可以在編譯環(huán)境的Setting...\C/C++ \ Code Generation項選擇。當(dāng)加在輸出函數(shù)前的關(guān)鍵字與編譯環(huán)境中的選擇不同時,直接加在輸出函數(shù)前的關(guān)鍵字有效。它們對應(yīng)的命令行參數(shù)分別 為/Gz、/Gd和/Gr。缺省狀態(tài)為/Gd,即__cdecl。
            要完全模仿PASCAL調(diào)用約定首先必須使用__stdcall調(diào)用約定,至于 函數(shù)名修飾約定,可以通過其它方法模仿。還有一個值得一提的是WINAPI宏,Windows.h支持該宏,它可以將出函數(shù)翻譯成適當(dāng)?shù)恼{(diào)用約定,在 WIN32中,它被定義為__stdcall。使用WINAPI宏可以創(chuàng)建自己的APIs。
            posted on 2007-12-26 14:06 sdfasdf 閱讀(567) 評論(0)  編輯 收藏 引用

            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            久久久精品午夜免费不卡| 99蜜桃臀久久久欧美精品网站| 久久国产热精品波多野结衣AV | 色偷偷888欧美精品久久久| 久久久久亚洲av无码专区喷水| 久久国产精品-久久精品| 久久99精品国产麻豆不卡| 久久无码AV中文出轨人妻| 国产精品欧美久久久天天影视 | 久久这里只有精品久久| 久久精品国产亚洲Aⅴ香蕉 | 区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 精品久久久久久国产| 国产成人精品综合久久久| 亚洲级αV无码毛片久久精品| 国产巨作麻豆欧美亚洲综合久久 | 久久精品国产亚洲综合色| 久久WWW免费人成一看片| 国产99久久久国产精免费| 亚洲国产精品无码久久久秋霞2 | 色综合久久精品中文字幕首页 | 国产精品久久久久无码av| 久久久无码精品亚洲日韩蜜臀浪潮| 久久精品国产亚洲欧美| 亚洲精品国产美女久久久| 亚洲国产成人精品无码久久久久久综合| 天堂久久天堂AV色综合| 久久精品国产亚洲AV香蕉| 亚洲?V乱码久久精品蜜桃 | 久久久久久国产精品美女| 国产亚洲美女精品久久久久狼| 香蕉久久夜色精品升级完成| 欧美一区二区久久精品| 久久久青草青青国产亚洲免观| 9191精品国产免费久久| a高清免费毛片久久| 久久精品国产亚洲av麻豆小说 | 色婷婷久久综合中文久久一本| 国产高清美女一级a毛片久久w | 日本强好片久久久久久AAA| 国产精品乱码久久久久久软件|