1.栈的介绍-C语言调用函数(二)

news2024/11/15 4:30:19

1.栈的介绍-C语言调用函数(一)_双层小牛堡的博客-CSDN博客

接着上面

函数调用的约定

在栈帧中 主要的是主调函数如何存入实参 让被调用函数能够访问

这种是通过函数见的调用规定来规范的

并且 调用规定还规范了 函数执行完后应该由主函数实现 清除参数 还是 被调用函数清除

被调用函数和主函数之间 是存在一个调用约定来保证程序的完整性

调用规定

调用规定通常规定了几个方面

(1)函数参数的传递顺序和方式
最常见的就是堆栈  主函数把实参压入栈内 被调用函数通过 相对ebp的偏移量 来访问函数的实参
如果有很多参数 调用规定还要确定参数入栈的顺序   (一些规定允许使用寄存器传参来提高速度)
(2)栈的维护
主函数调用被调用函数的时候 把参数压入 并且把控制器交给函数 
函数结束的时候 要把返回值弹出 并且清空栈帧 恢复到调用前的样子
这个通过约定来保证是 主函数或被调用函数进行清空
(3)名字修饰策略
又叫做函数名修饰策略 编译器对于不同函数 要进行确定名字修饰



如果函数之间的调用约定不匹配 那么就会出现错误 

常见的调用约定

cdecl约定

这个约定是在C++/C语言编译器 默认的函数调用方式

所有非C/C++的函数成员和不是使用 stdcall/fastcall定义的函数 都默认使用该调用约定

函数参数按照从从右到左入栈
void stack_test1(int a, int b, int c)
c 先压入 b 再压入 最后压入 a


并且主函数负责清空栈帧

可以使用于参数不固定的函数 例如printf

返回值放入EAX中

C语言的函数名修饰规则 是在函数名前加一个_
C++的规则是 除非特别使用 return "C" 否则使用不同的名字来修饰

stdcall约定

Pascall程序调用约定 WinApi也都是调用这个约定

约定函数参数从右往左入栈 
除了指针和引用类型外 全部使用传值的方式传递

被调用函数负责清除栈帧

返回值返回到EAX中


只能适用于 参数固定的函数


函数修饰 是 在函数名前面加_ 在函数后加@ 并且加入大小


例如
_functionname@number

number是函数参数的大小

fastcall

是stdcall的变形

使用 ECX EDX 传递前两个 四字节双字或更少字节的参数

参数从右往左入栈 
被调用函数清空栈帧

返回到EAX 中

因为两个寄存器存储 不用全部入栈 所以速度比stdcall更快 


函数名修饰

运用 @@修饰函数名 后面加上十进制数表示参数列表大小


@function_name@number

thiscall约定

C++中 非静态函数必须要接受一个指向主函数对象的类的指针 (this指针)并且频繁使用

主函数的对象地址必须要被调用函数提供

并且在调用被调用函数的时候 必须要把指针作为参数传递给被调用函数

编译器默认使用这个约定来应对非静态函数

函数参数从右往左入栈
如果参数是固定数目 那么this指针通过ECX传递给被调用函数
被调用函数清空栈帧
如果参数不是固定数目的 那么this指针在所有参数入栈后再继续入栈
主函数清空栈帧

thiscall只能编译器使用 这个不是函数

naked call

该约定 不能 没有保存和恢复寄存器的代码 并且不能使用ret来返回值

只能通过内嵌汇编返回

这个约定是在特殊情况下使用

声明处于非C/C++上下文中的函数,并由程序员自行编写初始化和清栈的内嵌汇编指令。

pascal约定

函数参数从左往右入栈
只能是固定参数
被调用函数自己清空栈帧


函数名修饰 只有全变为大写

我们继续给出图片来理解

 这张图我们就能清晰的看到每个约定的内容 和不同

现在我们给出代码 例子 来演示 如果我们在设立代码的时候 确定约定 主函数和被调用函数的汇编

int __attribute__((__cdecl__)) CalleeFunc(int i, int j, int k){
// int __attribute__((__stdcall__)) CalleeFunc(int i, int j, int k){
//int __attribute__((__fastcall__)) CalleeFunc(int i, int j, int k){
    return i+j+k;
}
void CallerFunc(void){
    CalleeFunc(0x11, 0x22, 0x33);
}
int main(void){
    CallerFunc();
    return 0;
}

 调用约定影响

如果函数导出被其他程序员执行的时候 应该遵循主调用约定 如果只是在内部 就根据函数的调用约定

x86函数参数传递方法

通过堆栈完成 并且存储顺序是从右往左存入

当主函数向被调用函数传参的时候

参数应该作为一个数组传入
因为是从右往左输入 
那么数组的下标  0,1,2.....n-1
就和函数参数声明是一样的 例如 int x(1,2,3,4)

各个类型的传参

整型和指针参数的传递

整型参数和指针参数传递的方式是一样的 因为在32位x86上 大小是一样的(四个字节)

对于被调用函数的栈帧

浮点参数的传递

其实和整型差不多 就是浮点型多占4个字节 总共占8个字节

结构体和联合体的参数

结构体和联合体都是c语言自定义的数据类型

两者最大的区别就是 对内存的处理不同

结构体  struct
可以包含很多成员 每个成员又可以有自己的名称和类型 互不干涉  遵循内存对齐原则
一个struct的长度为所有成员的总和


联合体 union
所有成员共用一块内存 并且同一时刻 只能有一个成员得到内存的控制

这两个的区别

在内存中 就是 结构体是存放了所有成员 联合体存放的只是需要的成员/被选中的

他们的参数存放和整型,浮点型差不多  只是存放的大小 传递在内存中的指针 来传递参数

x86返回值的传递方法

函数的返回值可以通过寄存器返回

(1)返回值不超过四字节(int,float,char,指针等) 通过EAX返回
(2)如果超过四字节小于八字节(longlong _int64等) 通过EAX+EDX返回 EDX返回值高4字节,EAX返回值低4字节
(3)如果返回值是浮点型(float,double) 就通过专用的协处理器浮点型栈的栈顶返回

浮点运算是需要专门的浮点处理器 所以需要专门的浮点栈返回

(4)如果是结构体和联合体 主函数会向被调用函数传入一个指向返回地址的参数
foo(p1,p2)-->foo(&p,p1,p2)
变为引用型参数返回
具有一下步骤

1.主函数将显示的实参逆序入栈
2.将接受返回值的结构体变量地址作为隐藏变量入栈 -->临时变量
3.被调用函数的返回值 拷贝到指向隐藏变量的地址中
4.把隐藏变量的地址存入EAX中 


不同的编译器有不同的方法
(5)不返回指向栈内存空间的指针 因为函数执行完毕后 会释放内存 如果返回了指针 会无法保证准确

函数返回值 通过寄存器返回 不需要分配空间来操作

所以如果不写返回的类型 就按照int类型返回 这会带来很大的安全隐患

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/464624.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[测试猿课堂]小白怎么学测试?史上最全《软件测试》学习路线

熬夜3天,联合3位猿计划教育的总监级授课老师,整理了这份《软件测试小白学习路线》,全文接近6000字,请大家耐心看完! 对于很多想通过自学转行软件测试的同学,痛点并不是学习动力,而是找不到清晰…

Apache SeaTunnel 3 分钟入门指南

简介 新一代分布式超高性能云原生数据同步工具 - Apache SeaTunnel 已经在B站、腾讯云、字节等数百家公司使用。 SeaTunnel 是 Apache 软件基金会下的一个高性能开源大数据集成工具,为数据集成场景提供灵活易用、易扩展并支持千亿级数据集成的解决方案。SeaTunnel …

《计算机网络--自顶向下方法》第三章--运输层

3.1概述和运输层服务 运输层协议为运行再不同主机上的应用进程之间提供了逻辑通信(logic communication)功能 运输层协议是在端系统中而不是在路由器中实现的 3.1.1运输层和网络层的关系 运输层协议至工作在端系统中 在端系统中,运输层…

基于Mybatis使用MySql存储过程,实现数据统计功能

1、前言 作为一个工作了很多年的程序员来说,没有在实际工作中真正使用过存储过程,其实对存储过程本身有过了解和学习,在日常的学习中,也会看过一些存储过程的相关介绍,不过“纸上得来终是浅”,正好这次做统…

Linux 利用网络同步时间

yum -y install ntp ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ntpdate ntp1.aliyun.com 创建加入crontab echo "*/20 * * * * /usr/sbin/ntpdate -u ntp.api.bz >/dev/null &" >> /var/spool/cron/rootntp常用服务器 中国国家授…

力扣sql中等篇练习(十三)

力扣sql中等篇练习(十三) 1 每位学生的最高成绩 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 #先找到最大的元素 然后分组即可,不用管某些字段(grade)是不是聚合字段 SELECT e1.student_id,min(e1.course_id) course_id,e1.grade FROM Enrollment…

setup.py方式打包自己的python代码并可以用pip install安装

setup.py方式打包自己的python代码并可以用pip install安装 所需文件及目录规范示例演示引用自己打的包 所需文件及目录规范 注意setup.py文件和MANIFEST.in文件需要放在和你需要打包的目录同一级下,例如我这里需要打包的就是webconsole文件夹(这里webc…

gl-opendrive插件(车俩3D仿真模拟自动驾驶)

简介 本插件基于免费opendrive开源插件、Threejs和Webgl三维技术、vue前端框架,blender开源建模工具等进行二次开发。该插件由本人独立开发以及负责,目前处于demo阶段,功能还需待完善,由于开发仓促代码还需优化。 因此&#xff…

35岁测试人,面临职场危机,打了一场漂亮的翻身仗...

“夜深知雪重,时闻折竹声”。雪折,一种在雪的载荷下,植物(多指树)的躯干或枝条被不断堆积的雪花压断的现象。我的刚刚经历了人生的第一次“雪折”。 我是一个有点聪明且勤奋好学的人,从考入省重点大学起&a…

Windows环境下C++ 安装OpenSSL库 源码编译及使用(VS2019)

参考文章https://blog.csdn.net/xray2/article/details/120497146 之所以多次一举自己写多一篇文章,主要是因为原文内容还是不够详细。而且我安装的时候碰到额外的问题。 1.首先确认一下自己的代码是Win32的还是Win64的,我操作系统是64的,忘…

java websocket实现聊天室 附源码

目录 1.Socket基础知识 2.socket代码实现 2.1 引入依赖 2.2 配置websocket 2.3 websocket的使用 2.4 webSocket服务端模块 2.5 前端代码 3.测试发送消息 4.websocket源码地址 1.Socket基础知识 Socket(套接字)用于描述IP地址和端口&#xff0c…

4年测试工作经验,跳槽之后面试20余家公司的总结

先说一下自己的个人情况,普通二本计算机专业毕业,懂python,会写脚本,会selenium,会性能,然而离职后到今天都没有收到一份offer!一直在待业中,从离职第一天就开始准备简历&#xff0c…

【Vue 基础】尚品汇项目-02-路由组件的搭建

项目路由说明: 前端的路由:Key-Value键值对 Key:URL(地址栏中的路径) Value:相应的路由组件 作用:设定访问路径,并将路径和组件映射起来(就是用于局部刷新页面&#xff0…

Vue+Openlayers+proj4实现坐标系转换

场景 Vue中使用Openlayers加载Geoserver发布的TileWMS: Vue中使用Openlayers加载Geoserver发布的TileWMS_霸道流氓气质的博客-CSDN博客 在上面的基础上实现不同坐标系坐标数据的转换。 Openlayers中默认的坐标系是EPSG:900913 EPSG:900913等效于EPSG:3857 可在…

kafka集群压测与优化

影响kafka集群性能的因数有多个,网络带宽、cpu、内存、磁盘读写速度、副本数、分区数、broker数量、内存缓存等因素都会影响kafka集群的性能 1.优化kafka集群配置 server.properties配置文件优化 num.network.threads4 num.io.threads4 socket.send.buffer.bytes…

提升供应链运营效率:企业如何规范化供应商关系?

在现代企业运营中,采购和供应链管理已成为至关重要的环节。企业尤其需要管理好自身供应商,才能够获得优质的原材料和零部件,并确保生产和销售的正常进行。本文将从供应商的筛选、双方合作的流程管理、团队建设等方面,为大家介绍如…

腾讯云COS+SpringBOot实现文件上传下载功能

文章目录 第一步:在.yml文件中配置对应秘钥内容第二步:完成COSConfig类编写第三步:编写Controller类Bug提示: 最近一直在做一个项目,需要支持视频,音频,图片的上传,前面介绍的都是把…

新一代边缘计算盒子,英码科技边缘计算盒子SY-E160

SY-E160 是英码科技推出的新一代智能工作站,内部集成了 4 核强悍处理器 A551.5 GHz,其内置的算力核拥有 16Tops 超强算力。SY-E160 工作站采用低功耗技术设计,支持 宽温度环境工作,可以灵活部署于各种 AI 场景中。 SY-E160 深元 A…

在SaleSmartly管理客户互动的 3 个好处

交互是关系的小组成部分。随着时间的推移,互动的质量决定了人们对这段关系的投入程度,同样的动态也适用于客户和品牌。在跨境电商业务中,每一次互动都是建立信任或失望的机会。 对于许多公司来说,客户互动的主要领域是客户服务功能…

机器学习 - Seaborn 练习, 常见功能查阅

机器学习记录 Seaborn Seaborn 是一个基于 Matplotlib 的 Python 可视化库,提供了一些内置数据集以及进行统计数据可视化和模型现场的 API。 sns.get_dataset_names() 方法会返回一个字符串列表,包含所有内置数据集的名称 练习 Seaborn 依赖Matplotlib, NumPy, SciPy, Pan…