军校是干什么的| 什么叫更年期| 木林森是什么品牌| 心识是什么意思| 鸡蛋吃多了有什么危害| tsh是什么意思| 隽字五行属什么| 单核细胞偏高说明什么| 家里飞蛾多是什么原因| 苔藓是什么植物| 什么是粉丝| 串联质谱筛查是什么病| 男人射精快吃什么药| 梦见别人送钱给我是什么意思| geo是什么意思| ACEI是什么药| 胃疼和肚子疼有什么区别| 一路走好是什么意思| 谷丙转氨酶高是什么原因| 什么时候需要做肠镜| 眼睛干涩用什么眼药水| 80年出生属什么生肖| 膀胱炎挂什么科| 小孩子流鼻血是什么原因| 小儿拉肚子吃什么药好得快| 什么私语| 雾霾是什么意思| 什么是化学阉割| 唉声叹气是什么意思| der是什么意思| 冰箱为什么老是结冰| 一个骨一个宽是什么字| 口腔长期溃疡是什么原因引起的| 凌晨两点多是什么时辰| 妇科检查白细胞酯酶阳性是什么意思| 贵州菜属于什么菜系| o型血为什么叫贵族血| 河北古代叫什么| 县副局长是什么级别| 舌苔黄腻是什么原因| 一个月一个并念什么| 头疼是什么引起的| 读书有什么好处| 病理单克隆抗体检测是什么| 绿豆什么时候收获| 心累是什么原因| mtd是什么意思| 什么的万里长城| 大姨妈来的少是什么原因| 怀才不遇是什么意思| 超声波检查是什么检查| 2006年是什么命| 小孩子流鼻血是什么原因引起的| 肝内结节是什么意思啊| 胆结石吃什么| 颈部淋巴结肿大挂什么科| 江字五行属什么| 胸口闷痛挂什么科| 汉语什么意思| 痴女是什么意思| 口蘑不能和什么一起吃| 睾丸萎缩是什么原因| 心什么神什么| 高烧用什么方法降温最快| 沫沫是什么意思| 破涕为笑是什么意思| 疱疹性咽峡炎是什么引起的| 绿色加红色是什么颜色| 吃什么利于排便| qm医学上什么意思| 紧张手抖吃什么药| 正月二十九是什么星座| 前列腺炎挂什么科| 合菜是什么| 熬夜对肾有什么影响| 慢性结肠炎吃什么药| 赡养是什么意思| 梦见生了个女儿是什么意思| 农垦局是什么性质单位| 耀字五行属什么| 皮肤过敏用什么药最好| 胆结石是什么症状| 恶寒是什么意思| 鸟字旁与什么有关| 利好是什么意思| 不完全骨折是什么意思| 中国精神是什么| 眩晕症吃什么药好| 4月份是什么季节| 十月初一是什么节| 衣原体检查是什么| 什么是次数| 甲状腺一度肿大是什么意思| 嗓子发炎吃什么消炎药| 舌苔黄是什么原因| 蒙脱石散是什么| ct与核磁共振有什么区别| 前期怀孕有什么症状| 中专什么时候报名| 屎发黑是什么原因| 咖啡加奶叫什么| 圆脸适合什么眉形| ABB式的词语有什么| 云朵像什么| 怀孕为什么会恶心想吐| 总胆红素高是什么意思| 肾亏是什么原因造成的| 总胆红素偏高什么意思| 拆线去医院挂什么科| 痔疮和肛周脓肿有什么区别| 宫颈炎吃什么药| 庆帝为什么杀叶轻眉| 鸭子喜欢吃什么| 铁树开花是什么生肖| 铅超标有什么症状| hpv59高危阳性是什么意思| 肱骨外上髁炎用什么药| 为什么会这样| 医院规培生是什么意思| 车前草长什么样子| 复试一般会问什么问题| 老公生日送什么礼物好| 什么是一本| 震撼是什么意思| 不显怀的人有什么特点| 北京晚上有什么好玩的景点| 简单明了是什么意思| hpv跟tct有什么区别| 莘莘学子是什么意思| 梦见眼镜蛇是什么预兆| 复三上坟是什么意思| 胎停是什么原因造成的| 白细胞偏低吃什么| 什么是佛跳墙| 糯米粉是什么粉| 蛀牙的早期症状是什么| 营卫不和是什么意思| 舌头烂了是什么原因| 痰多吃什么化痰| 谷子是什么意思| 艺高人胆大什么意思| a216是什么材质| 腋下是什么经络| 脑梗是什么引起的| 经常落枕是什么原因引起的| 梅花在什么季节开放| 下嘴唇发麻什么病兆| si是什么元素| 骨髓抑制是什么意思| 三教九流什么意思| 天天喝绿茶有什么好处和坏处| 闰6月有什么说法| 省委巡视组组长什么级别| 征兵什么时候开始| 尿道炎吃什么药最好| 北京大学校长是什么级别| 九月二十四号是什么星座| 左上腹疼是什么原因| 尿路感染吃什么药效果好| 孩子注意力不集中缺什么微量元素| 海带与什么食物相克| 宵字五行属什么| 女人多吃什么补黄体酮| 1974年是什么年| 鱼可以吃什么| 蔻驰手表属于什么档次| 社保缴费基数和工资有什么关系| 曹操是个什么样的人| 机灵的动物是什么生肖| 神仙是什么生肖| 什么的晚霞| 木乐读什么| 三七粉什么颜色| 柠檬水有什么好处| 马跟什么生肖最配| 狗咬人后狗为什么会死| 为什么辰不能见亥| tid什么意思| 2027是什么年| 什么是优质蛋白食物| 牙周炎用什么药最见效| 敖是什么意思| 儿童说话晚去医院挂什么科| 五谷丰收是什么生肖| 读书破万卷下一句是什么| 岚的意思是什么| 清醒的反义词是什么| 病毒感染咳嗽吃什么药效果好| 正切是什么| 阳痿吃什么好| 孔雀男是什么意思| ep什么意思| 五月二十四号是什么星座| darling是什么意思| 月台是什么意思| 幽门螺杆菌吃什么药最好| 胰腺检查挂什么科| 地球为什么叫地球| 无印良品属于什么档次| 浮生若梦是什么意思| 一片哗然是什么意思| 什么笑容| 律的右边读什么| 凡士林是什么东西| 胃酸吃什么可以缓解| tvb为什么演员都走了| 醛固酮高有什么危害| 漫反射是什么意思| 荔枝晒干了叫什么| 子宫内膜息肉有什么症状| 渡劫什么意思| 什么情况下吃丹参滴丸| 什么林什么染| 经常打呼噜是什么原因| 初心是什么意思| eb是什么意思| 牡丹王是什么茶| 1288是什么意思| essence什么意思| 每天吃一个西红柿有什么好处| 血小板上升是什么原因| 剪什么样的发型好看| 四风是什么| 肉桂属于什么茶类| 十一月六号是什么星座| 红牛什么时候喝效果好| 你要什么| 什么原因会怀上葡萄胎| 热射病什么症状| 在什么| 胡萝卜和什么不能一起吃| 618是什么星座| 福泽深厚什么意思| 五行属性是什么| 雪燕有什么功效| nb是什么意思| 海棠花的花语是什么| 小学教师需要什么学历| 阿尔马尔是什么药| 海狗是什么| 六甲什么意思| 右大腿上部疼痛是什么原因| 为什么饿的很快| 生完孩子可以吃什么水果| 什么不什么什么| 施华蔻属于什么档次| 行长是什么级别| 总胆固醇是什么| 大地色眼影是什么颜色| 58年属什么| 佛家思想的核心是什么| 股骨头坏死什么原因| 孕妇血糖高对胎儿有什么影响| 吃什么让月经量增多| 血钾是什么意思| 计划生育是什么意思| 乳头大是什么原因| 飞行模式有什么用| 交运是什么意思| omega3是什么| 嘴角上火是什么原因| 黄体酮低吃什么补得快| 枉然是什么意思| qrs波代表什么| 百度

新闻中心

EEPW首页 > 函数调用规范

从“三不沿”到“三临近”——贵州探索开放新路

——
作者: 时间:2025-08-07 来源: 收藏
 
百度 我想这是整个中华民族非常可贵的地方。

当高级语言被编译成机器码时,有一个问题就必须解决:因为CPU没有办法知道一个需要多少个、什么样的参数。即计算机不知道怎么给这个函数传递参数,传递参数的工作必须由函数者和函数本身来协调。为此,计算机提供了一种被称为栈的数据结构来支持参数传递。

   函数调用时,调用者依次把参数压栈,然后调用函数,函数被调用以后,在堆栈中取得数据,并进行计算。函数计算结束以后,或者调用者、或者函数本身修改堆栈,使堆栈恢复原装。在参数传递中,有两个很重要的问题必须得到明确说明:

  1) 当参数个数多于一个时,按照什么顺序把参数压入堆栈;

  2) 函数调用后,由谁来把堆栈恢复原装。

3)函数的返回值放在什么地方

在高级语言中,通过函数调用(Calling Conventions)来说明这两个问题。常见的调用有:

stdcall

cdecl

fastcall
thiscall naked call

stdcall调用规范

stdcall很多时候被称为pascal调用规范,因为pascal是早期很常见的一种教学用计算机程序设计语言,其语法严谨,使用的函数调用约定是stdcall。在Microsoft C++系列的C/C++编译器中,常常用PASCAL宏来声明这个调用约定,类似的宏还有WINAPI和CALLBACK。

stdcall调用规范声明的语法为:

int __stdcall function(int a,int b)
stdcall的调用约定意味着:
  1)参数从右向左压入堆栈;

  2)函数自身修改堆栈;

  3) 函数名自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸。

以上述这个函数为例,参数b首先被压栈,然后是参数a,函数调用function(1,2)调用处翻译成汇编语言将变成:
  push 2          第二个参数入栈

  push 1          第一个参数入栈

  call function   调用参数,注意此时自动把cs:eip入栈

而对于函数自身,则可以翻译为:
  push  ebp               保存ebp寄存器,该寄存器将用来保存堆栈的栈顶指针,可以在函数退出时恢复

  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           恢复esp

  pop   ebp

  ret   8

而在编译时,这个函数的名字被翻译成_function@8

注意不同编译器会插入自己的汇编代码以提供编译的通用性,但是大体代码如此。其中在函数开始处保留esp到ebp中,在函数结束恢复是编译器常用的方法。

从函数调用看,2和1依次被push进堆栈,而在函数中又通过相对于ebp(即刚进函数时的堆栈指针)的偏移量存取参数。函数结束后,ret 8表示清理8个字节的堆栈,函数自己恢复了堆栈。

 

cdecl调用规范

cdecl调用约定又称为C调用约定,是C语言缺省的调用约定,它的定义语法是:

  int function (int a ,int b)           // 不加修饰就是C调用约定

  int __cdecl function(int a,int b)     // 明确指出C调用约定

  cdecl调用约定的参数压栈顺序是和stdcall是一样的,参数首先由有向左压入堆栈。所不同的是,函数本身不清理堆栈,调用者负责清理堆栈。由于这种变化,C调用约定允许函数的参数的个数是不固定的,这也是C语言的一大特色。对于前面的function函数,使用cdecl后的汇编码变成:

  调用处

  push   1

  push   2

  call   function

  add    esp,8              注意:这里调用者在恢复堆栈

  

  被调用函数_function处

  push   ebp                保存ebp寄存器,该寄存器将用来保存堆栈的栈顶指针,可以在函数退出时恢复

  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            恢复esp

  pop    ebp

  ret                       注意,这里没有修改堆栈

MSDN中说,该修饰自动在函数名前加前导的下划线,因此函数名在符号表中被记录为_function。

由于参数按照从右向左顺序压栈,因此最开始的参数在最接近栈顶的位置,因此当采用不定个数参数时,第一个参数在栈中的位置肯定能知道,只要不定的参数个数能够根据第一个后者后续的明确的参数确定下来,就可以使用不定参数,例如对于sprintf函数,定义为:

 

int sprintf(char* buffer,const char* format,...)

由于所有的不定参数都可以通过format确定,因此使用不定个数的参数是没有问题的。

 

fastcall调用规范

fastcall调用约定和stdcall类似,它意味着:
  1) 函数的第一个和第二个DWORD参数(或者尺寸更小的)通过ecx和edx传递,其他参数通过从右向左的顺序压栈;

  2) 被调用函数清理堆栈;

  3) 函数名修改规则同stdcall。

其声明语法为:int __fastcall function(int a,int b)

 

thiscall调用规范

thiscall是唯一一个不能明确指明的函数修饰,因为thiscall不是关键字。它是C++类成员函数缺省的调用约定。由于成员函数调用还有一个this指针,因此必须特殊处理,thiscall意味着:

  1) 参数从右向左入栈;

  2) 如果参数个数确定,this指针通过ecx传递给被调用者;如果参数个数不确定,this指针在所有参数压栈后被压入堆栈;

  3) 对参数个数不定的,调用者清理堆栈,否则函数自己清理堆栈。

为了说明这个调用约定,定义如下类和使用代码:
class A

{

public:

        int function1(int a,int b);

        int function2(int a,...);

};

int A::function1 (int a,int b)

{

        return a+b;

}

int A::function2(int a,...)

{

        va_list ap;

        va_start(ap,a);

        int i;

        int result = 0;

        for(i = 0 ; i < a ; i ++)

        {

                result += va_arg(ap,int);

        }

        return result;

}

void callee()

{

        A a;

        a.function1(1,2);

        a.function2(3,1,2,3);

}

callee函数被翻译成汇编后就变成:
  // 函数function1调用

  0401C1D    push        2

  00401C1F   push        1

  00401C21   lea         ecx,[ebp-8]

  00401C24   call   function1             注意,这里this没有被入栈

  // 函数function2调用

  00401C29   push        3

  00401C2B   push        2

  00401C2D   push        1

  00401C2F   push        3

  00401C31   lea         eax,[ebp-8]      这里引入this指针

  00401C34   push        eax

  00401C35   call   function2

  00401C3A   add         esp,14h

可见,对于参数个数固定情况下,它类似于stdcall,不定时则类似cdecl

 

naked call调用规范

这是一个很少见的调用约定,一般程序设计者建议不要使用。编译器不会给这种函数增加初始化和清理代码,更特殊的是,不能用return返回返回值,只能用插入汇编返回结果。这一般用于实模式驱动程序设计,假设定义一个求和的加法程序,可以定义为:
   __declspec(naked) int  add(int a,int b)

   {

       __asm mov eax,a

       __asm add eax,b

       __asm ret

   }

注意,这个函数没有显式的return返回值,返回通过修改eax寄存器实现,而且连退出函数的ret指令都必须显式插入。上面代码被翻译成汇编以后变成:
   mov    eax,[ebp+8]

   add    eax,[ebp+12]

   ret    8

注意这个修饰是和__stdcall及cdecl结合使用的,前面是它和cdecl结合使用的代码,对于和stdcall结合的代码,则变成:
   __declspec(naked) int __stdcall function(int a,int b)

   {

       __asm mov eax,a

       __asm add eax,b

       __asm ret 8        //注意后面的8

   }

至于这种函数被调用,则和普通的cdecl及stdcall调用函数一致。

 

函数调用约定导致的常见问题

如果定义的约定和使用的约定不一致,则将导致堆栈被破坏,导致严重问题,下面是两种常见的问题:
1) 函数原型声明和函数体定义不一致

2) DLL导入函数时声明了不同的函数约定


关键词: 调用 规范 函数

评论


相关推荐

技术专区

关闭
开火是什么意思 什么尾巴长不了 女朋友生日送什么 骨质疏松吃什么钙片 荨麻疹吃什么食物好
什么平稳 bp是什么 心慌气短吃什么药 脾虚湿重吃什么中成药 梅开二度是什么意思
鼻子干燥是什么原因 十点半是什么时辰 容易紧张是什么原因 来月经吃什么排得最干净 什么叫化疗为什么要化疗
为什么没有广东大学 心跳过快是什么原因 下一个台风什么时候来 胆疼是什么原因 肠胃感冒什么症状
打了鸡血是什么意思zsyouku.com 福星是什么意思hcv8jop9ns1r.cn 贫血去医院挂什么科hcv9jop7ns2r.cn 女生的阴道长什么样hcv8jop6ns0r.cn 什么洗发水最好hcv9jop1ns4r.cn
瓜子脸剪什么发型好看hcv9jop3ns7r.cn 什么是cthcv8jop3ns2r.cn 女人乳房疼是什么原因hcv8jop9ns2r.cn 类风湿吃什么药hcv8jop0ns5r.cn 外阴瘙痒用什么效果好hcv9jop6ns4r.cn
灰色鞋子搭配什么颜色裤子hcv8jop6ns5r.cn 高胆红素血症是什么病hcv8jop8ns7r.cn 农历八月十五是什么节日hcv8jop9ns2r.cn 什么是龟头炎hcv9jop4ns3r.cn 恶风是什么意思hcv8jop9ns8r.cn
色素沉着有什么办法可以去除1949doufunao.com 第一次见面送女生什么花travellingsim.com 梦到吃饭是什么意思zsyouku.com 牙周炎用什么药yanzhenzixun.com 怀孕初期胸部有什么变化hcv9jop3ns0r.cn
百度