一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

__cdecl __stdcall區(qū)別

 書永夜 2014-03-13
最大的區(qū)別就是__cdecl是由調(diào)用函數(shù)者釋放堆棧,而__stdcall由被調(diào)用者釋放。但是我們?cè)谡{(diào)用任一種函數(shù)時(shí),都沒有進(jìn)行顯示的釋放堆棧工作。這個(gè)工作由編譯器完成,它幫我們生成了這個(gè)中間要使用的代碼。

       以下系轉(zhuǎn)載:     

     在C語(yǔ)言中,假設(shè)我們有這樣的一個(gè)函數(shù):
  
  int function(int a,int b)
  
  調(diào)用時(shí)只要用result = function(1,2)這樣的方式就可以使用這個(gè)函數(shù)。但是,當(dāng)高級(jí)語(yǔ)言被編譯成計(jì)算機(jī)可以識(shí)別的機(jī)器碼時(shí),有一個(gè)問題就凸現(xiàn)出來(lái):在CPU中,計(jì)算機(jī)沒有辦法知道一個(gè)函數(shù)調(diào)用需要多少個(gè)、什么樣的參數(shù),也沒有硬件可以保存這些參數(shù)。也就是說(shuō),計(jì)算機(jī)不知道怎么給這個(gè)函數(shù)傳遞參數(shù),傳遞參數(shù)的工作必須由函數(shù)調(diào)用者和函數(shù)本身來(lái)協(xié)調(diào)。為此,計(jì)算機(jī)提供了一種被稱為棧的數(shù)據(jù)結(jié)構(gòu)來(lái)支持參數(shù)傳遞。

  棧是一種先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu),棧有一個(gè)存儲(chǔ)區(qū)、一個(gè)棧頂指針。棧頂指針指向堆棧中第一個(gè)可用的數(shù)據(jù)項(xiàng)(被稱為棧頂)。用戶可以在棧頂上方向棧中加入數(shù)據(jù),這個(gè)操作被稱為壓棧(Push),壓棧以后,棧頂自動(dòng)變成新加入數(shù)據(jù)項(xiàng)的位置,棧頂指針也隨之修改。用戶也可以從堆棧中取走棧頂,稱為彈出棧(pop),彈出棧后,棧頂下的一個(gè)元素變成棧頂,棧頂指針隨之修改。
  函數(shù)調(diào)用時(shí),調(diào)用者依次把參數(shù)壓棧,然后調(diào)用函數(shù),函數(shù)被調(diào)用以后,在堆棧中取得數(shù)據(jù),并進(jìn)行計(jì)算。函數(shù)計(jì)算結(jié)束以后,或者調(diào)用者、或者函數(shù)本身修改堆棧,使堆?;謴?fù)原裝。
  在參數(shù)傳遞中,有兩個(gè)很重要的問題必須得到明確說(shuō)明:
  
  當(dāng)參數(shù)個(gè)數(shù)多于一個(gè)時(shí),按照什么順序把參數(shù)壓入堆棧 
  函數(shù)調(diào)用后,由誰(shuí)來(lái)把堆?;謴?fù)原裝 
  在高級(jí)語(yǔ)言中,通過函數(shù)調(diào)用約定來(lái)說(shuō)明這兩個(gè)問題。常見的調(diào)用約定有:
  stdcall 
  cdecl 
  fastcall 
  thiscall 
  naked call

  stdcall調(diào)用約定
  stdcall很多時(shí)候被稱為pascal調(diào)用約定,因?yàn)閜ascal是早期很常見的一種教學(xué)用計(jì)算機(jī)程序設(shè)計(jì)語(yǔ)言,其語(yǔ)法嚴(yán)謹(jǐn),使用的函數(shù)調(diào)用約定就是stdcall。在Microsoft C++系列的C/C++編譯器中,常常用PASCAL宏來(lái)聲明這個(gè)調(diào)用約定,類似的宏還有WINAPI和CALLBACK。
  stdcall調(diào)用約定聲明的語(yǔ)法為(以前文的那個(gè)函數(shù)為例):
  
  int __stdcall function(int a,int b)
  
  stdcall的調(diào)用約定意味著:1)參數(shù)從右向左壓入堆棧,2)函數(shù)自身修改堆棧 3)函數(shù)名自動(dòng)加前導(dǎo)的下劃線,后面緊跟一個(gè)@符號(hào),其后緊跟著參數(shù)的尺寸
  以上述這個(gè)函數(shù)為例,參數(shù)b首先被壓棧,然后是參數(shù)a,函數(shù)調(diào)用function(1,2)調(diào)用處翻譯成匯編語(yǔ)言將變成:
  push 2        第二個(gè)參數(shù)入棧
  push 1        第一個(gè)參數(shù)入棧
  call function    調(diào)用參數(shù),注意此時(shí)自動(dòng)把cs:eip入棧
  而對(duì)于函數(shù)自身,則可以翻譯為: 
  push ebp       保存ebp寄存器,該寄存器將用來(lái)保存堆棧的棧頂指針,可以在函數(shù)退出時(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í),這個(gè)函數(shù)的名字被翻譯成_function@8
  注意不同編譯器會(huì)插入自己的匯編代碼以提供編譯的通用性,但是大體代碼如此。其中在函數(shù)開始處保留esp到ebp中,在函數(shù)結(jié)束恢復(fù)是編譯器常用的方法。
  從函數(shù)調(diào)用看,2和1依次被push進(jìn)堆棧,而在函數(shù)中又通過相對(duì)于ebp(即剛進(jìn)函數(shù)時(shí)的堆棧指針)的偏移量存取參數(shù)。函數(shù)結(jié)束后,ret 8表示清理8個(gè)字節(jié)的堆棧,函數(shù)自己恢復(fù)了堆棧。
  
  cdecl調(diào)用約定
  cdecl調(diào)用約定又稱為C調(diào)用約定,是C語(yǔ)言缺省的調(diào)用約定,它的定義語(yǔ)法是:
  int function (int a ,int b) //不加修飾就是C調(diào)用約定
  int __cdecl function(int a,int b)//明確指出C調(diào)用約定
  在寫本文時(shí),出乎我的意料,發(fā)現(xiàn)cdecl調(diào)用約定的參數(shù)壓棧順序是和stdcall是一樣的,參數(shù)首先由右向左壓入堆棧。所不同的是,函數(shù)本身不清理堆棧,調(diào)用者負(fù)責(zé)清理堆棧。由于這種變化,C調(diào)用約定允許函數(shù)的參數(shù)的個(gè)數(shù)是不固定的,這也是C語(yǔ)言的一大特色。對(duì)于前面的function函數(shù),使用cdecl后的匯編碼變成:
  調(diào)用處
  push 1
  push 2
  call function
  add esp, 8     注意:這里調(diào)用者在恢復(fù)堆棧
  被調(diào)用函數(shù)_function處
  push ebp       保存ebp寄存器,該寄存器將用來(lái)保存堆棧的棧頂指針,可以在函數(shù)退出時(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         注意,這里沒有修改堆棧
  MSDN中說(shuō),該修飾自動(dòng)在函數(shù)名前加前導(dǎo)的下劃線,因此函數(shù)名在符號(hào)表中被記錄為_function,但是我在編譯時(shí)似乎沒有看到這種變化。
  由于參數(shù)按照從右向左順序壓棧,因此最開始的參數(shù)在最接近棧頂?shù)奈恢?,因此?dāng)采用不定個(gè)數(shù)參數(shù)時(shí),第一個(gè)參數(shù)在棧中的位置肯定能知道,只要不定的參數(shù)個(gè)數(shù)能夠根據(jù)第一個(gè)后者后續(xù)的明確的參數(shù)確定下來(lái),就可以使用不定參數(shù),例如對(duì)于CRT中的sprintf函數(shù),定義為: 
  int sprintf(char* buffer,const char* format,...)
  由于所有的不定參數(shù)都可以通過format確定,因此使用不定個(gè)數(shù)的參數(shù)是沒有問題的。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    亚洲中文字幕综合网在线| 五月婷婷综合缴情六月| 国产91色综合久久高清| 日韩和欧美的一区二区三区| 婷婷开心五月亚洲综合| 日本一级特黄大片国产| 国产伦精品一区二区三区精品视频| 99久久精品久久免费| 老司机精品视频在线免费| 国产美女网红精品演绎| 欧美日韩亚洲国产精品| 成人精品国产亚洲av久久| 国产免费人成视频尤物| 国产肥妇一区二区熟女精品| 99热九九在线中文字幕| 日韩国产亚洲一区二区三区| 亚洲国产精品肉丝袜久久| 成人精品国产亚洲av久久| 成人精品一级特黄大片| 99久久免费中文字幕| a久久天堂国产毛片精品| 欧美黑人暴力猛交精品| 国产午夜福利不卡片在线观看| 日本高清中文精品在线不卡| 亚洲第一区二区三区女厕偷拍| 精品al亚洲麻豆一区| 欧美亚洲综合另类色妞| 日韩精品小视频在线观看| 高清亚洲精品中文字幕乱码| 亚洲国产色婷婷久久精品| 亚洲中文字幕日韩在线| 亚洲国产成人精品福利| 人妻中文一区二区三区| 国产精品午夜福利免费在线| 人妻亚洲一区二区三区| 免费观看日韩一级黄色大片| 久久精品中文字幕人妻中文| 亚洲国产成人爱av在线播放下载 | 在线观看免费视频你懂的| 国产一区麻豆水好多高潮| 黄色美女日本的美女日人|