成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

函數(shù)調(diào)用的三種約定,你都清楚嗎

開發(fā) 后端
三種調(diào)用方式的區(qū)別相信大家應(yīng)該有些了解,這篇文章主要從實例和匯編的角度闡述這些區(qū)別的表現(xiàn)形態(tài),使其對它們的區(qū)別認(rèn)識從理論向?qū)嶋H過渡。

 __cdecl、__stdcall、__fastcall是C/C++里中經(jīng)常見到的三種函數(shù)調(diào)用方式。其中__cdecl是C/C++默認(rèn)的調(diào)用方式,__stdcall是windows API函數(shù)的調(diào)用方式,只不過我們在頭文件里查看這些API的聲明的時候是用了WINAPI的宏進行代替了,而這個宏其實就是__stdcall了。

三種調(diào)用方式的區(qū)別相信大家應(yīng)該有些了解,這篇文章主要從實例和匯編的角度闡述這些區(qū)別的表現(xiàn)形態(tài),使其對它們的區(qū)別認(rèn)識從理論向?qū)嶋H過渡。

我們知道,函數(shù)的調(diào)用過程是通過函數(shù)棧幀的不斷變化實現(xiàn)的:

函數(shù)的調(diào)用,涉及參數(shù)傳遞,返回值傳遞,調(diào)用后返回,這都是通過棧的變化來實現(xiàn)的,對于三種調(diào)用約定而言:

__cdecl:

C/C++默認(rèn)方式,參數(shù)從右向左入棧,主調(diào)函數(shù)負(fù)責(zé)棧平衡。

__stdcall:

windows API默認(rèn)方式,參數(shù)從右向左入棧,被調(diào)函數(shù)負(fù)責(zé)棧平衡。

__fastcall:

快速調(diào)用方式。所謂快速,這種方式選擇將參數(shù)優(yōu)先從寄存器傳入(ECX和EDX),剩下的參數(shù)再從右向左從棧傳入。因為棧是位于內(nèi)存的區(qū)域,而寄存器位于CPU內(nèi),故存取方式快于內(nèi)存,故其名曰“__fastcall”。

下面從實例來認(rèn)識一下這三種調(diào)用約定。先來看一個簡單的不能再簡單的程序了:

 

三個函數(shù)的內(nèi)容都是一樣的,不同的是使用了三種調(diào)用的方式。我們先來看看在main函數(shù)調(diào)用三個函數(shù)的時候的匯編代碼: 

按照上面說的那樣,__cdecl按照參數(shù)從右向左的方式進入棧區(qū),注意Fun1()和Fun3()的區(qū)別,F(xiàn)un1()在call Fun1()之后執(zhí)行了add esp,8。這一操作正是我們前面所說的進行棧的平衡。調(diào)用函數(shù)之前連續(xù)進行了兩次push操作將函數(shù)所需的實參5和2先后壓入了棧區(qū),調(diào)用完成后,我們需要恢復(fù)調(diào)用前的狀態(tài),則需調(diào)整棧頂指針esp的位置,這一工作由誰來完成就決定了兩種函數(shù)調(diào)用方式__cdecl(主調(diào)函數(shù)完成)和__stdcall(被調(diào)函數(shù)完成)的區(qū)別。上圖我們看到了__cdecl中由主調(diào)函數(shù)完成了,那么__stdcall呢,在被調(diào)函數(shù)Fun3()中,轉(zhuǎn)向被調(diào)函數(shù)結(jié)尾處的代碼,我們看到了這一句:

那么Fun1()結(jié)尾處又是如何呢?

看到了吧,這個ret指令后面跟沒跟值就決定了函數(shù)返回是棧指針ESP需要增加的量。這樣,不需要主調(diào)函數(shù)再調(diào)用add指令為ESP操作平衡棧區(qū),節(jié)約了程序的開銷,一條指令開銷小,如果十萬百萬個這樣的調(diào)用,這個開銷就明顯了。

說完了__cdecl和__stdcall,再來看看__fastcall,如前面圖看到的調(diào)用時并未使用push指令向棧里傳參數(shù),而是使用了

  mov  edx, 5

  mov  ecx, 2

兩條指令。這樣直接將參數(shù)傳入寄存器,被調(diào)函數(shù)在執(zhí)行的時候直接從寄存器取值即可,省去了從棧里取出來給寄存器,再從寄存器取出來放入內(nèi)存。

不過,說個題外話,ecx寄存器經(jīng)常作為計數(shù)和C++里this指針的傳遞媒介。在這種情況下,情況又是怎樣的呢,下次分析C++操作符 new 的時候再予以討論。ecx做計數(shù)器時,需要將ecx中存儲的實參先壓入棧區(qū),計數(shù)操作完成后再pop出來。如此一來,這個fastcall倒顯得不那么fast了。

當(dāng)然,上面所說的這些操作都是由編譯器在背后為我們完成的,開發(fā)人員無需關(guān)心這些操作,對我們是透明的。不過,知其然更知其所以然方能立于不敗之地! 

 

責(zé)任編輯:龐桂玉 來源: C語言與C++編程
相關(guān)推薦

2019-05-08 10:50:37

交換機組網(wǎng)網(wǎng)絡(luò)

2021-09-13 13:05:05

Redis數(shù)據(jù)庫內(nèi)存

2023-08-04 08:25:03

客戶配置Spring

2023-02-27 23:45:09

MySQL索引存儲

2023-09-22 08:01:10

2023-09-14 23:14:57

MySQL索引

2023-02-02 14:24:08

物聯(lián)網(wǎng)數(shù)據(jù)分析云平臺

2021-02-25 23:40:26

Redis集群架構(gòu)

2011-01-18 15:35:59

jQueryJavaScriptweb

2022-01-10 07:57:25

Linux 插樁Linux 系統(tǒng)

2024-11-26 07:47:41

2022-07-09 15:37:14

數(shù)字化轉(zhuǎn)型企業(yè)數(shù)字化

2020-09-11 06:39:29

ThreadLocal線程

2021-10-10 12:29:27

機器人AI人工智能

2025-06-06 00:00:00

JavaHTTPMCP

2024-08-13 08:25:16

C#外部程序方式

2016-09-18 22:47:57

分布式存儲GFSAFSLustre

2017-02-20 17:15:43

分布式存儲文件系統(tǒng)

2010-02-03 15:46:15

C++函數(shù)傳遞

2024-05-27 00:20:00

點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产小视频在线观看 | 日韩成人免费视频 | 在线中文字幕国产 | 91精品国产综合久久婷婷香蕉 | 成人免费看黄网站在线观看 | 午夜寂寞影院在线观看 | 久久国产一区二区三区 | 国产在线视频一区 | 中文字幕一区二区不卡 | 粉嫩一区二区三区性色av | 亚洲欧美激情四射 | www.中文字幕av | 亚洲视频中文字幕 | 一区二区三区精品视频 | 亚洲精品视频一区二区三区 | 在线欧美小视频 | 国产午夜视频 | 久久久久久国模大尺度人体 | 亚洲午夜精品在线观看 | 日韩在线成人 | 国产精品久久久久久久久免费樱桃 | 91精品国产色综合久久 | 久久精品国产99国产精品 | 亚洲一区三区在线观看 | 久久99精品视频 | 性一交一乱一伦视频免费观看 | 国产精品久久久久免费 | 国产精品欧美一区二区 | 国产91亚洲精品一区二区三区 | 日韩欧美在 | 91亚洲精品久久久电影 | 一区二区福利视频 | 欧美黄色片在线观看 | 欧美专区在线视频 | 欧美亚洲成人网 | 中文字幕在线第一页 | www.亚洲精品 | 亚洲国产一区视频 | 亚洲久久一区 | 一区二区三区av夏目彩春 | 国产一区二区三区四区hd |