当前位置: 首页 > news >正文

【C++】汇编分析,函数是如何调用,传参,返回

传参

有的是用寄存器传参,有的用push传参
我在MSVC编译测出来的是PUSH传参(debug模式),具体过程如下

long func(long a, long b, long c, long d,long e, long f, long g, long h) {long sum;sum = (a + b + c + d + e + f + g + h);return sum;
}int main() {long sum;sum = func(1, 2, 3, 4, 5, 6, 7, 8);std::cout << sum << std::endl;return 0;
}

调用方:

汇编
在这里插入图片描述

push 是将操作数压到栈顶,然后移动栈顶(esp)
push前:
在这里插入图片描述
push一次后:
在这里插入图片描述
call前:
在这里插入图片描述

进入函数func

汇编
在这里插入图片描述
分析:

  1. 前3条是经典的移动堆栈
    移动后:
    在这里插入图片描述
    注意这个ebp = 00ff68c, 理论上它应该是等于call前的esp即00ff694,为何相差8。
    参数和栈底ebp之间的这8个字节分别是两个地址,先是函数的返回地址,即call指令的下一条地址,call指令是先将下一条指令地址压入栈然后跳转;其次是函数调用方的ebp,由跳转后第一条指令push ebp写入。
    具体栈信息如图:
    在这里插入图片描述

返回值

在这里插入图片描述

可见是通过eax寄存器返回的。

总结

可以回答以下几个问题:

  1. 如何传参,通过push指令将参数压入栈,然后call
  2. 参数放在哪:因为调用是先push再call, 进入函数后参数在栈下面,也就是不在[ebp, esp)这个范围内,通过ebp+x来取得参数。
  3. 局部变量在哪:进入函数后的3条指令开辟了新的栈空间即[ebp, esp), 局部变量在栈空间内,通过ebp-x来取值。
  4. 函数执行完恢复调用方的堆栈信息:进入函数后先将调用方的ebp压入栈,然后移动堆栈,调用方的ebp就存在当前栈底,即ebp指向的就是,退出函数时有个mov esp, ebp;pop ebp 动作就是将栈底的值给ebp寄存器。就恢复了调用方的堆栈
  5. 返回值,返回值简单时通过寄存器返回。
  6. 为什么参数的入栈信息总是从右到左:栈是向上增长的,先入栈的参数处于高位地址,压栈完后从低地址往高地址看,参数顺序就是从左向右了。
  7. ret指令: 跳转到当前栈顶的地址,然后esp-4
  8. call指令:将下一条指令地址压入栈,然后esp+4
  9. 调用函数栈信息如下:
//func的栈
-esp
...
-ebp   ----- 调用方的ebp
-ebp-4  返回地址
- ebp-8 参数1
- ...
- 参数 n

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 四种NAT类型
  • OpenCVSharp中的图像数据结构与类型
  • 【PyQt6 应用程序】视频百叶窗效果一键生成模块
  • Android Studio gradle下载太慢了!怎么办?(已解决)
  • RO通讯数据包
  • Linux实现异步IO的方法:epoll,posix aio,libaio,io_uring
  • Datawhale x李宏毅苹果书AI夏令营深度学习详解进阶Task03
  • 基于生成对抗模型GAN蒸馏的方法FAKD及其在EdgesSRGAN中的应用
  • OpenGuass under Ubuntu_22.04 install tutorial
  • 基于Python实现AES加密与解密
  • 《QDebug 2024年8月》
  • 深度学习(二)-损失函数+梯度下降
  • 【数据结构】-----哈希
  • 【科研新手必备】如何高效、高质量、科学的科研?
  • 仿论坛项目--第二部分习题
  • 【comparator, comparable】小总结
  • Docker: 容器互访的三种方式
  • E-HPC支持多队列管理和自动伸缩
  • Electron入门介绍
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • java取消线程实例
  • js 实现textarea输入字数提示
  • Mysql数据库的条件查询语句
  • Solarized Scheme
  • Wamp集成环境 添加PHP的新版本
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 用Python写一份独特的元宵节祝福
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • #QT(TCP网络编程-服务端)
  • (1)Hilt的基本概念和使用
  • (pojstep1.1.2)2654(直叙式模拟)
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (一)Linux+Windows下安装ffmpeg
  • (原)Matlab的svmtrain和svmclassify
  • (原创)可支持最大高度的NestedScrollView
  • .Net FrameWork总结
  • .NET 同步与异步 之 原子操作和自旋锁(Interlocked、SpinLock)(九)
  • .Net8 Blazor 尝鲜
  • .Net的DataSet直接与SQL2005交互
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • ??eclipse的安装配置问题!??
  • [AndroidStudio]_[初级]_[修改虚拟设备镜像文件的存放位置]
  • [Codeforces1137D]Cooperative Game
  • [Day 44] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
  • [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated c
  • [FC][常见Mapper IRQ研究]
  • [hdu 1711] Number Sequence [kmp]
  • [k8s源码]6.reflector
  • [Linux打怪升级之路]-信号的保存和递达
  • [NCTF2019]True XML cookbook
  • [NOI2022] 众数 题解
  • [Nuget]使用Nuget管理工具包
  • [Pyhton]weakref 弱引用
  • [Redis]哨兵机制