【C++进阶】__stdcall 详解

【C++进阶】__stdcall 详解

    __stdcall用来修饰函数,被该关键字修饰的函数,其参数都是从右向左依次被压入到栈中,函数调用在返回前需要清理堆栈,被调函数在返回前负责清理堆栈。

函数调用约定    

    函数调用约定主要约束了两件事:
1. 参数传递的顺序
2. 调用堆栈由谁(调用函数或被调用函数)负责清理

    __stdcall是函数调用约定的一种。__stdcall表示:
1. 参数从右向左压入堆栈(这样当函数参数出栈时,刚好是先拿到最左边的参数)
2. 函数被调用者修改堆栈,负责清理自己在堆栈中的参数
3. 函数名(在编译器层次)自动加前导下划线,后面紧跟着一个@符号,其后紧跟着参数的尺寸。因此,声明为 int func( int a, int b ) 的函数修饰如下所示:_func@8

以上述这个函数为例,参数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个字节的堆栈,函数自己恢复了堆栈。


注:以上内容参考了网络上的其它内容,如有错误,请在回复中指出。




  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值