(转载)函数调用方式比较

【图解函数调用过程】【转载】 函数调用是编程语言都有的概念,也许你听说过函数调用栈,但是大家都知道函数调用是如何完成的吗?我们为什么要了解这个过程:对于程序运行机制中的数据结构和实现的了解,对自己开发程序有着启发作用碰到一些疑难杂症的时候,比如函数栈溢出了或者函数栈破坏了,如何从蛛丝马迹中寻找问题的原因。了解栈溢出可能带来的危害,黑客也许会利用栈溢出的漏洞进行攻击。这篇博文我们一起来对函数调用的过程进行探究。 阅读详情

对于各种的call,看看汇编的结果很清楚,  例如对于函数:  
  void   func(int   a,   int   b,   int   c,   int   d)   {   }  
  使用函数如下  
  int   main()  
  {  
  func(1,   2,   3,   4);  
  }   

1.如果函数func是__cdecl(默认调用方式),调用时情况如下  
  int   main()  
  {  
  //参数从右到左压栈  
  push   4  
  push   3  
  push   2  
  push   1  
  call   func  
  add   esp   0x10   //调用者恢复堆栈指针esp,4个参数的大小是0x10(4x4)  
  }  
   
  2.如果函数func是__stdcall,调用时情况如下  
  int   main()  
  {  
  //参数从右到左压栈  
  push   4  
  push   3  
  push   2  
  push   1  
  call   func  
                //恢复堆栈指针由被调用者func负责,方法是"ret   0x10"  
  }  
   
  3.如果函数func是__pascal,调用情况如下  
  int   main()  
  {  
  //参数从左到右压栈  
  push   1  
  push   2  
  push   3  
  push   4  
  call   func  
  //恢复堆栈指针由被调用者func负责,方法是"ret   0x10"  
  }   
    
 4.如果函数func是__fastcall,调用情况如下  
  int   main()  
  {  
  //参数先用ecx,   edx,   eax传递,然后再压栈  
  //不进栈  
  //(不知为什么,帮助中写的是从左到右传递的,  
  //是不是错了,还是BCB6和BCB5的不一样)  
  push   4  
  mov   ecx 3  
  mov   edx 2  
  mov   eax 1  
  call   func  
  //恢复堆栈指针由被调用者func负责,方法是"ret   0x04",  
  //因为只进栈一个参数,其余用寄存器传递,所以用ret   0x04恢复  
  }   
    
   

函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)

Posted on Tuesday, May 24, 2005 3:23 PM #C & C++ href="http://blog.bcchinese.net/happyjet/Services/Pingback.aspx" rel="pingback" />

 

__cdecl

 

 

__stdcall

 

C 和 C++ 程序的缺省调用规范

 

为了使用这种调用规范,需要你明确的加上 __stdcall (或 WINAPI )文字。即 return-type __stdcall function-name[(argument-list)]

 

 

在被调用函数 (Callee) 返回后,由调用方 (Caller) 调整堆栈。

 

1. 调用方的函数调用

                                         

2. 被调用函数的执行

 

3. 被调用函数的结果返回

 

4. 调用方清除调整堆栈

                                                                

 

在被调用函数 (Callee) 返回前,由被调用函数 (Callee) 调整堆栈。图示:

 

1. 调用方的函数调用

 

2. 被调用函数的执行

 

3. 被调用函数清除调整堆栈

 

4. 被调用函数的结果返回                                                           

 

因为每个调用的地方都需要生成一段调整堆栈的代码,所以最后生成的文件较大。

 

 

因为调整堆栈的代码只存在在一个地方(被调用函数的代码内),所以最后生成的文件较小。

 

函数的参数个数可变(就像 printf 函数一样),因为只有调用者才知道它传给被调用函数几个参数,才能在调用结束时适当地调整堆栈。

 

 

函数的参数个数不能是可变的。

 

对于定义在 C 程序文件中的输出函数,函数名会保持原样,不会被修饰。

对于定义在 C++ 程序文件中的输出函数,函数名会被修饰, MSDN 说 Underscore character (_) is prefixed to names . 我实际测试( VC4 和 VC6 )下来发现好像不是那么简单。

可通过在前面加上 extern “C” 以去除函数名修饰。也可通过 .def 文件去除函数名修饰。

 

不论是 C 程序文件中的输出函数还是 C++ 程序文件中的输出函数,函数名都会被修饰。

对于定义在 C 程序文件中的输出函数, An underscore (_) is prefixed to the name. The name is followed by the at sign (@) followed by the number of bytes (in decimal) in the argument list.

对于定义在 C++ 程序文件中的输出函数,好像更复杂,和 __cdecl 的情况类似。

好像只能通过 .def 文件去除函数名修饰。

 

 

_beginthread 需要 __cdecl 的线程函数地址

 

 

_beginthreadex 和 CreateThread 需要 __stdcall 的线程函数地址

 

 

两者的参数传递顺序都是从右向左。

为了让 VB 可以调用,需要用 __stdcall 调用规范来定义 C/C++ 函数。请参看Microsoft KB153586 文章:How To Call C Functions That Use the _cdecl Calling Convention。

当你 LoadLibrary 一个 DLL 文件后, 把 GetProcAddress 取得的函数地址传给上面三个线程生成函数时,请务必确认实际定义在 DLL 文件的输出函数符合调用规范要求。否则,编译成 Release 版后运行,可能会破坏堆栈,程序行为不可预测。

VC 中的相关编译开关:/Gd /Gr /Gz。另外,VC6中新增加的 /GZ 编译开关可以帮你检查堆栈问题。

我也是初学者,若有不对的地方、可以补充的地方,请指教。谢谢。  

 

(补充)汇编语言视点的比较文章: Intel x86 Function-call Conventions - Assembly View


<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
C++函数调用运算符重载 函数调用运算符重载 函数调用运算符 () 也可以重载 由于重载后使用的方式非常像函数的调用,因此称为仿函数 仿函数没有固定写法,非常灵活 示例: class MyPrint { public: void operator()(string text) { cout << text << endl; } }; void test01() { //重载的()操作符 也称为仿函数 MyPrint myFunc; myFunc("hello world"); } 阅读详情

相关推荐

实战分享:如何用YOLOv5s+BIFPN高效检测隧道裂缝(附数据集获取)

本文详细介绍了如何利用YOLOv5s结合BIFPN(双向特征金字塔网络)构建高效的隧道裂缝智能检测系统。文章从高质量数据集构建、针对性数据增强、模型架构选型与调优,到工程化部署全链路进行了实战分享,旨在为基础设施自动化巡检提供兼顾精度与速度的解决方案。

weixin_29062823的博客 380

linux动态库调用优先级,Linux动态库搜索路径优先级问题 第二个人的理解

Linux动态库搜索路径优先级问题 第二个人的理解发布时间:2008-05-05 21:09:39来源:红联作者:zisxvdmc作者:annight E-mail:annightzhao@gmail.com5月5日今天学习LINUX的动态库的搜索优先级当运行GCC,将先把程序经过编译器生成 .o文件,该文件不能直接运行,需再次生成可执行文件,才可被系统运行。如果程序中涉及到调用库函数时候,这时...

weixin_30366435的博客 557

手把手教你用Sentinel-1和SNAP处理InSAR数据:从下载到生成沉降图(附Python脚本)

本文详细介绍了如何使用Sentinel-1数据和SNAP软件处理InSAR数据,从下载到生成地表沉降图的全流程。通过Python脚本实现自动化处理,适用于城市扩张和地质脆弱带的地表沉降监测,提供高性价比的毫米级形变监测方案。

weixin_26800111的博客 267

浅谈——程序执行和函数的调用

以前写一个程序,只知道编译,在无错后就直接运行了,然后看看结果是不是自己想要的,结果对了然后就啥也不管了,如果错了就只会一行一行的看自己的代码,看看问题在哪(大多数时候,看了半天也不知道问题在哪),经过最近的学习了解,才知道一个程序的运行也不是我所想的那么简单。 初步了解了一个程序的运行包括了,预处理,编译,汇编,链接等过程,这些过程下面又分了很多的子过程,要想真正的去了解他,要学习的还有很多。

haishark的博客 1689

Landsat9 地表温度反演方法

landsat9地表温度反演及缺失值处理方法

xiangliu12345的博客 3918

LSTM 怎么进行二维数据的输入呢

尽管LSTM并不天然地适用于处理图像、视频等二维数据,但通过时间序列化、卷积特征提取和双向LSTM等方法,我们可以将二维数据转化为适合LSTM输入的形式,从而利用LSTM的强大记忆能力和长期依赖学习能力对二维数据进行建模。未来的研究方向可以考虑将LSTM与其他模型结合,例如将LSTM与卷积神经网络(Convolutional Neural Network, CNN)结合,利用CNN提取图像的空间特征,然后利用LSTM学习时间序列的长期依赖;

xiamu_CDA的博客 1037

关于函数的定义、调用和执行

认识函数(定义-执行-销毁(执行空间)) 1-先定义 2-再调用 在JS函数中,数值是先赋值,再进预解析 function fn(a){ console.log(a); function a(){} } fn(100);//ƒ a(){} 说明在函数中,先赋值,再进行预解析 一个不销毁的执行空间 在函数执行空间中,函数代码执行结束,则执行空间销毁,函数内的变量也会销毁; 若想要保存函数内的变量,怎么办? 答:在函数内返回一个引用数据类型(数组、对象、函数),并且

weixin_42943920的博客 946

某验SVG图标验证码识别思路(非训练)

本文提出了一种无需训练的某验SVG图标验证码识别方法。通过分析SVG文件结构,使用正则表达式提取静态图标数据,并借助CairoSVG库转换为PNG格式。随后采用坐标定位方式裁剪出12个固定位置的图标,最后利用ResNet50提取特征,通过余弦相似度匹配目标图标。该方法避免了训练目标检测模型,实现了高效准确的验证码识别。关键步骤包括SVG文件预处理、图标定位裁剪和基于预训练模型的相似度比对。

九月镇灵将的博客 419

函数的定义与调用

函数的定义与调用

m0_64332867的博客 377

农业无人机:无人机图像处理_(8).遥感图像处理与分析

遥感图像处理与分析在农业无人机技术中具有重要作用,通过图像预处理、特征提取、分类与分割、目标检测等技术,可以实现对农田的精细管理、作物监测、病虫害预测等应用。本节详细介绍了这些技术的基本概念、常用方法和具体实现,希望对您在农业无人机图像处理方面的学习和应用有所帮助。

zhubeibei168的博客 1336

【优化模型】求解混合整数线性规划 MILP 问题

混合整数线性规划(Mixed Integer Linear Programming,MILP)是一类优化问题,其中目标函数和约束条件均为线性,并且包含整数变量。MILP 在实际应用中具有广泛的应用,可以解决很多实际问题,如生产调度、网络设计、资源分配等。f — 系数向量。系数向量,指定为实数向量或实数数组。intcon — 整数约束组成的向量。整数约束组成的向量,指定为正整数向量。intcon 中的值指示决策变量 x 中应取整数值的分量。A — 线性不等式约束。线性不等式约束,指定为实矩阵。

Fanjufei的博客 2497

C语言函数的调用——比较两个数的大小

目录 一、先写好框架 二、然后定义我们需要的变量 三、这里就要写函数的部分 四、函数部分写完了,但是还一个地方,要值得注意 一、常规方法比较大小 二、指针操作比较大小 今天我们要写的是用调用函数的方法来 比较两个数字的大小 我们先看看程序的运行效果 一、先写好框架 #include<stdio.h> void main() { } 二...

欢迎来到Gorit的博客 6万+

uniapp [微信小程序] - 实现语音播报功能+实时收款播报,使用同声传译插件做文字转语音播报类似微信/支付宝收款播报小程序语音识别和朗读,手机提醒播放自定义收款语音信息(音频+收款金额+文案)

uniapp-实现语音播报功能,实时收款播报,uni-app/vue 文字转语音朗读(附小程序语音识别和朗读)uniapp小程序使用文字转语音播报类似支付宝收款播报小程序语音识别和朗读)IOS苹果手机播报没有声音,生成语音并播放,微信小程序接入官方wechatSi(微信同声传译)uniapp小程序使用文字转语音播报类似支付宝收款播报,uni-app 小程序端实现文字语音播报,uniAPP文本转语音,uniapp 文字转语音文字播报,手机静音播放没声音,收款方提示音 文字转语音朗读 同声传译,uniapp小程

🏆 前端领域优质创作者 3795

【翻译、转载】【转载】LLM 的函数调用与 MCP

函数调用是一种机制,允许 LLM 根据用户输入识别它需要什么工具以及何时调用它。LLM 接收来自用户的提示。LLM 决定它需要的工具。程序员实现程序来接受来自 LLM 的工具调用请求,并准备一个函数调用。函数调用(带有参数)被传递给将处理实际执行的后端服务。让我们快速看看实际操作!首先,我们定义一个工具函数。它使用yfinance库来获取指定股票代码的最新收盘价:【参考】# (示例 Python 代码,定义 get_stock_price 函数)

计算机视觉之光 1211

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

【转载】SAP比较常用的几个接口方式及比较

1.PI - 信使中间件 (大公司多选择) 数据: SAP- PI- U8 U8- PI- SAP PI 底层用的还是webservice 技术 优点:实时性高; 可处理大数据(在调用PROXY 发送时 还可以分包处理); 有接口数据日志在PI系统; 缺点:PI 服务器+1; PI系统配置工作; 和每个外部系统都要做wsdl配置; 2. RFC - 函数 (小公司 / 简单业务场景使用) ...

hubaichun的专栏 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

函数调用的三种方式

'''1 什么是调用函数 函数名(...)即调用函数,会执行函数体代码,直到碰到return结束或者一直运行完毕所有代码2 为何要调用函数 用函数的功能3、函数调用分为三种形式 max2(1,2) res=max2(3000,2000) * 12 res=max2(max2(1000,2000),3000)函数定义时 在代码块之前加上“”“         ...

ZHOUXIN0426的博客 3374

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

函数调用的4种方式

一、函数调用的4种模式 1、函数调用 function foo() { alert('hello'); } foo();注意:this 专指全局对象 window 2、方法调用 // 定义一个函数 var foo = function() { alert("我是一个函数么?"); }; // 将其赋值给一个对象 var...

weixin_33716154的博客 1025

函数调用栈比较有意思

函数调用栈比较有意思作者:liigo原文链接:http://blog.youkuaiyun.com/liigo/archive/2006/12/23/1456938.aspx转载请注明出处:http://blog.youkuaiyun.com/liigo 昨天和海洋一块研究了下函数调用栈,顺便写两句。不足或错误之处请包涵!理解调用栈最重要的两点是:栈的结构,EBP寄存器的作用。首先要认识到这样两个

周狼赤壁的技术博客 2540

函数指针的初始化以及函数调用的三种方式

【c和指针学习笔记】函数指针的初始化以及函数调用的三种方式 2015年09月28日 21:29:20zyh_helen阅读数 3331 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.youkuaiyun.com/ZongYinHu/article/details/48790555 看如下代码,然后思考如下几个问题:(9+条消息)【c和指针学习笔记】函数指针的...

weixin_41632560的博客 1972

【转载】函数调用方式--__thiscall调用方式和__cdecl,__stdcall有什么区别

原文链接:https://blog.youkuaiyun.com/u014269285/article/details/80503180 函数调用方式–__thiscall调用方式和__cdecl,__stdcall有什么区别 首先,__thiscall是关于类的一种调用方式,它与其他调用方式的最大区别是: __thiscall对每个函数都增加了一个类指针参数 class aa { void bb(i...

gclome的博客 265

中断触发方式的比较(转载)

中断触发方式的比较 在前后台系统或者带有OS的系统,中断处理程序是相对比较难的,对系统的性能影响比较大。在带有OS的系统中,中断作为一个异步事件,还可以引发任务调度。在带有OS的系统中我们经常会关闭中断,而在ISR中我们...

weixin_30745553的博客 1254

转载——比较器的原理

比较器的原理

m0_37327467的博客 4655

优快云转载的方式

起意        看到一篇不错的博客,想转载但是不会(没有转载键),网搜发现没有Chrome浏览器的详细转载办法 实践 检查。在喜欢的博客页面右键(用快捷键ctrl+shift+I也行只是比较难找到相应想要的html码)选择“检查...

weixin_57619565的博客 112

IT168转载问题解决情况,以及本人博客转载方式

与IT168编辑联系之后,目前文章已添加原文链接,并且答应以后的各类转载都会符合协议。这个结局比较令人满意。此外,我想在这里详细谈一下这方面的一些做法。 转载方式简介 首先,请注意每篇文章下方都有一个Licence链接,如下: 点击上面的图标或链接“共享 2.5 中国大陆”,将会进入...

chuifuhuo6864的博客 114

Ruby中的各种比较方式对比

Ruby中设计了很多种比较方式,所有对象都能进行==、!=、===、<=>、eql?、equal?这几种比较。此外,当实现了<=>之后,如果还include了Comparable之后,就会自动获得<=、<、==、>=、>、between?这几个比较方法。 这些比较方法的定义位置和意义分别如下。 在BasicObject中定义了: ==:比较内容是...

weixin_30315723的博客 355
上一篇: 读史记——刘敬叔孙通列传第三十九(1)
下一篇: 找工作(1)——微软
llmlx
博客等级 码龄23年 15粉丝 105原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值