函数调用约定

函数调用约定

栈其实就是进程中的一块内存空间,其大小被记录在PE头中,也就是说当进程运行时,栈的大小就已经确定了

栈主要是用来存放常量,变量,函数参数以及函数返回地址等

当函数执行完的时候,ESP的值要恢复到调用前的值,这样才能保证栈的大小不会变化

怎样才能保证ESP的值恢复?

有三种主要方式,也就是函数调用约定

三种调用约定

cdecl

主要是在C语言中使用的约定,由调用者负责处理栈

在这里插入图片描述

看一下这里的CALL 401020;

在调用函数之前压入了3个参数到栈,这个时候ESP是往上(低地址)移动了12个字节(每个参数4个字节),通过上面介绍我们知道,函数调用前后,不管如何,ESP要恢复原值

再看ADD ESP,0C;

者条指令将ESP加了12个字节,即将ESP恢复了原值,从而栈大小保持不变

这种由函数调用者来处理栈参数的方式就是cdecl约定

cdecl约定的好处就在于可以向被调用函数传递可变的参数(就像printf()函数那样),这种传递可变长度的参数在其他约定中很难实现

stdcall

常用于WIN32 API,由被调用者清理栈

在这里插入图片描述

可以看到main函数中调用401000后并没有恢复栈,

而是在被调用函数中最后有个RETN 8,这个就是清理栈的指令,它表示返回然后ESP+8,这种由被调用者自行清理栈的方式就是stdcall

用stdcall的好处是代码尺寸小,兼容性好

fastcall

与stdcall类似,不同之处在于fastcall利用了ECX,EDX寄存器

如果函数有多个参数,前2个参数就被分别放入ECX,EDX中,后面的参数再被放入栈中,也是由被调用者清理栈

fastcall的优点快,函数调用非常快,因为访问寄存器比内存快得多,但有时候函数复杂,ECX,EDX有别的用处,就需要先备份数据到其他地方,再使用ECX,EDX保存函数的前2个参数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值