函数调用约定

在参数传递中,有两个很重要的问题必须得到明确说明:
当参数个数多于一个时,按照什么顺序把参数压入堆栈函数调用后由谁来把堆栈恢复原装。在高级语言中,通过函数调用约定来解决这两个问题。常见的调用约定有:
stdcallcdeclfastcallthiscallnaked call

1, __cdecl(C调用约定.The C default calling convention)C/C++ 缺省调用方式 
  1)压栈顺序:函数参数从右到左 
  2)参数栈维护:由调用函数把参数弹出栈,传送参数的内存栈由调用函数来维护 
  (正因为如此,实现可变参数vararg的函数(如printf)只能使用该调用约定) 
  3)函数修饰名约定:VC将函数编译后会在函数名前面加上下划线前缀 

  4)每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大 

   (5) 由主程序执行“ADD ESP, n”指令调整 ESP,达到堆栈平衡。

 
2, __stdcall (Pascal方式清理C方式压栈,通常用于Win32 Api中) 
  1)压栈顺序:函数参数从右到左的压栈顺序 
  2)参数栈维护:被调用函数把参数弹出栈(在退出时清空堆栈)
 3)函数修饰名约定:VC将函数编译后会在函数名前面加上下划线前缀,在函数名后加上"@"和参数的字节数
    ex. VC: int f(void *p) (编译后)->  _f@4 (在外部汇编语言里可以用这个名字引用这个函数) 

  4)由子程序通过调用“RET n”指令主动平衡


3, __fastcall (快速调用约定,通过寄存器来传送参数) 
  1)压栈顺序:用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送 
  2)参数栈维护:被调用函数在返回前清理传送参数的内存栈 
  3)函数修饰名约定:VC将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数 
 
4, thiscall (本身调用,仅用于“C++”成员函数) 
  1)压栈顺序:this指针存放于CX/ECX寄存器中,参数从右到左的压栈顺序 

  2)thiscall不是关键词,因此不能被程序员指定 

如果参数个数确定,this指针通过ecx传递给被调用者;如果参数个数不确定,this指针
在所有参数压栈后被压入堆栈。
对参数个数不定的,调用者清理堆栈,否则函数自己清理堆栈
可见,对于参数个数固定情况下,它类似于stdcall,不定时则类似cdecl

 
5, naked call (裸调) 
这是一个很少见的调用约定,一般程序设计者建议不要使用。 一般用于实模式驱动程序设计 .

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值