VINPI 之 _stdcall详解.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
VINPI 之 _stdcall详解 你可以查看WINAPI的定义,它是这样定义的 #define WINAPI _stdcall 可以发现CALLBACK也是这样定义的 _stdcall规定了编译时的一些选项. 对_stdcall 的理解 在C 语言中,假设我们有这样的一个函数:int function(int a,int b) 调用时只要用result = function(1,2)这样的方式就可以使用这个 函数。但是,当高级语言被编译成计算机可以识别的机器码时,有一 个问题就凸现出来:在CPU 中,计算机没有办法知道一个函数调用 需要多少个、什么样的参数,也没有硬件可以保存这些参数。也就是 说,计算机不知道怎么给这个函数传递参数,传递参数的工作必须由 函数调用者和函数本身来协调。为此,计算机提供了一种被称为栈的 数据结构来支持参数传递。 栈是一种先进后出的数据结构,栈有一个存储区、一个栈顶指 针。栈顶指针指向堆栈中第一个可用的数据项(被称为栈顶)。用户 可以在栈顶上方向栈中加入数据,这个操作被称为压栈(Push),压栈 以后,栈顶自动变成新加入数据项的位置,栈顶指针也随之修改。用 户也可以从堆栈中取走栈顶,称为弹出栈(pop),弹出栈后,栈顶下 的一个元素变成栈顶,栈顶指针随之修改。函数调用时,调用者依次 把参数压栈,然后调用函数,函数被调用以后,在堆栈中取得数据, 并进行计算。函数计算结束以后,或者调用者、或者函数本身修改栈, 使堆栈恢复原装。 在参数传递中,有两个很重要的问题必须得到明确说明: 当参数个数多于一个时,按照什么顺序把参数压入堆栈函数调用后, 由谁来把堆栈恢复原装。在高级语言中,通过函数调用约定来说明这 两个问题。常见的调用约定有: 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

文档评论(0)

htfyzc + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档