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

【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.
    首先push ebp让esp向下移动4,剩下的4是函数返回地址,即call指令的下一条指令地址
    具体栈信息如图:
    在这里插入图片描述
    可以看到栈从下往上,先压入了参数,后压入了call前的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

http://www.kler.cn/a/282220.html

相关文章:

  • vueRouter路由切换时实现页面子元素动画效果, 左右两侧滑入滑出效果
  • GPU分布式通信技术-PCle、NVLink、NVSwitch深度解析
  • 【MySQL】MySQL的笛卡尔积现象是什么?简单说说
  • vuex和pinia的区别
  • Linux从0——1之shell编程4
  • Pytest从入门到精通
  • 【软件工程】软件工程
  • Oracle(87)如何判断是否需要重建索引?
  • 计算机毕业设计选题推荐-救援物资管理系统-Java/Python项目实战
  • numpy 中的降维与升维
  • 编程路上的“迷宫逃脱”:从Bug堆到算法之巅的奇妙之旅
  • Renesa Version Board和微信小程序通信
  • sqli-labsSQL手工注入第26-30关
  • scrapy--图片管道-ImagesPipeline
  • 第十五章、 Io流
  • 风控领域特征工程
  • 力扣: 移除链表元素
  • 2017年系统架构师案例分析试题一
  • 使用C++,仿照string类,实现myString
  • 符合开闭原则的设计模式
  • 如何使用 Qt C++ 基于 FFmpeg 开发本地视频播放器
  • Kafka·Producer
  • 通过历史进行数据预测的算法
  • 云计算实训39——部署Harbor、部署Docker-compose、YAML文件
  • Win11 操作(七)声音降噪
  • 【JVM】亿级流量调优(一)