函数调用的过程理解_汇编角度

news2025/1/18 20:22:22

目录

  • 1、调用函数流程(main函数调用print函数):
    • Step1 保存main函数现场地址等信息
    • Step2 跳转到print函数的位置
    • Step3 执行print函数的指令
    • Step4 返回main函数,执行下一条指令
    • 流程连续性总结
  • 2、其他知识总结

1、调用函数流程(main函数调用print函数):

Step1. 保存main函数现场地址等信息

Step2. 跳转到print函数的位置

Step3. 执行print函数的指令

Step4. 返回main函数,执行下一条指令

Step1 保存main函数现场地址等信息

要存储的内容,主要有3个:

(1)传入print函数的形参【父函数中实现】

(2)原eip(main函数call指令的下一条指令的地址)【父函数中实现】

(3)原ebp(main函数的ebp地址,因为是main函数直接调用print函数)【子函数中实现】

实现方式:

main函数中,依次执行以下指令:

push eax; # 传入函数的形参arg
call print; #作用是保存eip。当然,也有跳转的作用(见Step2)

print函数开头,依次执行以下指令:

push ebp; # 保存父函数main函数的栈底地址,方便调用函数结束后pop回去
mov ebp esp; # 指定print函数的栈帧基地址(print函数对应的栈底地址)

Step2 跳转到print函数的位置

核心是修改eip寄存器,把eip寄存器的值,修改为print函数的入口地址。

实现方式:main函数中调用call指令

call print.77c70888; # 相当于esp = esp - 4; push eip(此时的eip值,就是下面"main函数中的下一条指令"的地址); mov eip print函数的地址77c70888(跳转到新函数)
main函数中的下一条指令;

Step3 执行print函数的指令

子函数最开始,一般要执行以下的命令:

push ebp; # 保存原ebp
mov ebp esp; # ebp指向当前函数的栈底
...
sub esp, num; # 为子程序分配栈空间
...
pop ebp; # 让ebp指向父函数的栈帧基地址
ret n; # 让eip指向“main函数call指令的下一条指令的地址”;n是指平衡堆栈,即让最先push进去的形参args清空

Step4 返回main函数,执行下一条指令

核心是修改eip寄存器的值,把eip寄存器的值,修改为main函数中下一条指令的地址。

实现方式:在print函数中,调用ret命令

ret ; #相当于pop eip; esp = esp + 4

注意,如果原先栈中还有其他数据,esp 没有归位会导致主函数引用栈中数据出错。在这种背景下,出现了堆栈平衡的概念。即,还需对esp 进行单独操作,才能将 esp 指向原函数栈顶。以常见的 c 语言,函数有好几种调用规则。比如 cdecl 方式和 stdcall 方式。

cdecl 方式中,由主程序执行 add esp, n 指令调整 esp,达到堆栈平衡。在 stdcall 方式中,由子程序在返回时,执行 ret n 平衡堆栈。n 其实就是函数的参数所占的空间大小。

流程连续性总结

重要参考:《从汇编角度理解 ebp&esp 寄存器、函数调用过程、函数参数传递以及堆栈平衡》

函数调用

在一个函数中,调用另外一个函数,往往有以下几个步骤:

汇编指令指令归属函数SP 变化作用
push arg2主函数sp-4
push arg1主函数sp-4
call function主函数sp-4开始调用子程序,同时保存返回地址
push ebp子函数sp-4
mov ebp, esp子函数sp-4将当前esp 存入 ebp,目的是定位函数参数
sub sp, #num子函数sp-num为子程序分配栈空间
子函数函数的具体实现逻辑
pop ebp子函数sp+4
ret子函数sp+4

说明:

  • push arg 在调用一个函数之前,需要把传递的参数压入栈,因此需要有。每次 push 之后,栈多了一个字长(32 位系统 --> 4 字节),因此栈顶需要往上移动 4 字节,该指令暗含 sub sp, #4
  • call call 指令用来调用某个函数,该指令有3个操作(1)sp = sp - 4(2)将返回地址压入栈; (3)修改eip
  • push ebpmov ebp, esp 这样的操作,你会在各个函数的开头见到,保存上一个函数栈的基址,并更新本函数的基址
  • ret,即 return,此时 sp 应该指向 call 指令刚刚压入的返回地址;执行 ret 其实就是将此时栈中的数据弹出,存至 eip 寄存器。eip 存放的是下一条即将执行的指令的地址。 同时 sp = sp + 4
  • ret 指令相当于 pop eip(esp = esp + 4)
  • call 指令相当于 push eip(esp = esp - 4); mov eip 新函数的地址

下图左边是主函数调用子函数,右边是子函数返回主函数:

在这里插入图片描述

2、其他知识总结

1、esp寄存器,永远指向整个栈帧的栈顶(esp寄存器保存的值是堆栈的地址值);栈顶中的内容,可能是一个地址值,也可能是一个立即数等等。esp寄存器指向的堆栈地址始终有值!所以push是先移esp后压栈,pop是先弹栈后移esp。

2、ebp寄存器,永远指向当前函数所在栈帧的栈底(ebp寄存器保存的值是堆栈的地址值);栈底中的内容,永远保存的是上一个函数(父函数)的ebp地址!(方便函数执行完后pop回去,即修改ebp)

  • ebp 的作用之一就是找到函数的形参(通过ebp + 偏移量),当然栈中的局部变量也是可以通过 ebp 来定位的(ebp - 偏移量)

3、父函数调用子函数,子函数的栈帧(低地址)是紧挨着父函数的栈帧(高地址)。

  • 所以父函数调用子函数,一定是①args先压榨 ② 然后 原eip压栈(by call)③ 再 ebp压栈 ④ 最后函数的局部变量压榨

  • 父函数栈帧 和 子函数栈帧,隔着的东西就是:args 和 eip

    在这里插入图片描述

4、栈的增长方向,永远向着低地址的方向增长。

5、call 指令相当于:esp = esp - 4; push eip; mov eip 函数的地址.77c70888 (注意,push中已包含esp移动,这里只是表示先后)

6、ret指令相当于:pop eip; esp = esp + 4 (注意,pop中已包含esp移动,这里只是表示先后)

7、push eax指令,只会修改栈和esp:① esp = esp - 4 ② mov [esp], eax 这个[esp]表示esp指向的栈值(内存值)被赋值。

8、pop eax指令,不仅会修改栈和esp,而且还会修改eax(寄存器被赋值):① mov eax, [esp] ②esp = esp + 4

9、寄存器的地址值是不会变的,变的只是寄存器中装的堆栈地址值,以及这个堆栈地址中的内存内容值。这个类似并区别于C语言的指针变量。C语言指针变量有2个地址值,一个是指针变量装的堆栈地址值,另一个是指针本身的地址值(也位于堆栈)。指针变量声明后,它存在于内存中(堆栈中),指针释放了,这个指针的地址值也就无了。区别点在于 指针有本身的地址值(可以通过&取出来),而寄存器没有本身的地址值的说法(取不出来,或者有也是固定的但不常用)。指针变量的常操作数据有3个:①p ②*p ③&p;esp寄存器常操作的数据有2个:①esp ②[esp]

  • esp:esp寄存器的内容值,即栈/内存的某个地址
  • [esp]:栈中的值 / 内存中的值

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

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

相关文章

竞赛报名管理系统asp.net+sqlserver

竞赛报名管理系统 功能简单 内容单调 适合学习 asp.net 三层架构 sqlserver2022数据库 账号登陆注册 用户管理 克赛管理 竞赛报名 竞赛评分 公告维护 修改密码 新增竞赛 2019数据库版本低 附加不了 需要高版本数据库 说明文档 运行前附加数据库.mdf(或sql生成数据…

24/8/4算法笔记 梯度下降

通过迭代地调整参数,沿着目标函数梯度的反方向(即最陡峭的下降方向)进行搜索,从而找到函数的局部最小值。 导入库 import matplotlib.pyplot as plt import numpy as np 构建方程和导数 #构建方程 f lambda x:(x-3.5)**2-4.…

代码随想录算法训练营第二天 | 209. 长度最小的子数组、59. 螺旋矩阵 II

目录 209. 长度最小的子数组1、题目描述2、思路3、code4、复杂度分析 LC59 螺旋矩阵 II1、题目描述2、思路3、code4、复杂度分析 209. 长度最小的子数组 题目链接:209 1、题目描述 给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其总和大于…

Netty一

Netty Netty介绍 Netty应用场景 I/O模型 阻塞IO 同步非阻塞IO 异步非阻塞IO BIO NIO AIO对比 Netty线程模型 Reactor模式 单Reactor单线程 单Reactor多线程 主从Reactor多线程 Netty模型 异步模型 Future-Listener机制 TCP粘包拆包基本介绍 Netty内存使用 Netty内存池化 Netty…

PCB设计

PCB设计 一、 元件封装是什么? 元件封装:一是指元件的包装方式,二是指元件的焊盘形状与尺寸。 在绘制PCB板的时候,要保证元件封装绘制正确,否则元件很可能无法焊接到成品板上。 不同的厂家生产的各类元器件的形状、尺…

用uniapp 及socket.io做一个简单聊天app 5

聊天中的通知及好友申请&#xff1a; 如下图效果 聊天的效果&#xff1a; 这里的friends&#xff0c;好友例表&#xff0c;里面有相关代码&#xff1a; <template><view class"friends-container"><view v-if"!isLoggedIn" class"…

【资治通鉴】“ 将欲取之、必先予之 “ 策略 ① ( 魏桓子 割让土地 | 资治通鉴原文分析 | 道德经、周书、吕氏春秋、六韬 中的相似策略 )

文章目录 一、" 将欲取之、必先予之 " 策略1、魏桓子 割让土地2、资治通鉴原文分析 二、" 将欲取之、必先予之 " 类似的原理1、将欲败之&#xff0c;必姑辅之&#xff1b;将欲取之&#xff0c;必姑与之 - 周书2、将欲歙之&#xff0c;必固张之&#xff0c;…

24年第五届“华数杯”数学建模竞赛浅析

需要完整资料&#xff0c;请关注WX&#xff1a;“小何数模”&#xff01; 本次华数杯数模比赛的赛题已正式出炉&#xff0c;无论是赛题难度还是认可度&#xff0c;该比赛都是仅次于数模国赛的独一档&#xff0c;可以用于国赛前的练手训练。考虑到大家解题实属不易&#xff0c;…

24/8/4算法笔记 线性回归

在简单或多元线性回归中&#xff0c;最小二乘法用来估计模型参数&#xff0c;使得预测值与实际值之间的差异&#xff08;残差&#xff09;的平方和最小。 最小二乘法 导入代码包 import numpy as np Xnp.array([[1,1],[2,1]]) X 构建矩阵 ynp.array([14,10]) y linalg是线…

电子电气架构 --- 域控制器在新架构中的功能承担

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

五. TensorRT API的基本使用-build-trt-module

目录 前言0. 简述1. 案例运行2. 代码分析2.1 main.cpp2.2 model.cpp2.3 network.hpp 3. 案例3.1 sample_cbr3.2 sample_resBlock3.3 sample_convBNSiLU3.4 sample_c2f 总结下载链接参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》&#xff0c;链接。记录下个人学…

力扣第五十二题——N皇后II

内容介绍 n 皇后问题 研究的是如何将 n 个皇后放置在 n n 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回 n 皇后问题 不同的解决方案的数量。 示例 1&#xff1a; 输入&#xff1a;n 4 输出&#xff1a;2 解释&#xff1a;如上图所…

C# ADC数据波形显示

1. 串口显示汉字的程序设计 using System; using System.Text; using System.Windows.Forms;namespace 汉字显示 {public partial class Form1 : Form{public Form1(){InitializeComponent();}private byte[] StringToBytes(string TheString){Encoding FromEncoding Encodin…

鼻咽癌综述

小罗碎碎念 本期推文主题&#xff1a;鼻咽癌综述 这篇文章提供了一个全面的综述&#xff0c;探讨了鼻咽癌&#xff08;NPC&#xff09;的关键研究进展&#xff0c;包括病理机制、治疗、筛查和生物标志物的发展。 文章首先强调了NPC在特定地理区域的流行情况&#xff0c;并讨论了…

微分方程的数值解法——Runge-Kutta (RK4)

Runge-Kutta (RK4)   The Runge-Kutta (RK4) methods are used to solve the solution of the non-liner ordinary differential equation. Here, we will simply summary this method.   Assume the Intial Value Piont (IVP) is satisfied: y ′ f ( t , y ) , y ( t 0 )…

深入底层源码,剖析AQS的来龙去脉!

这里写目录标题 回顾前缀知识一、Condition的概念二、Condition底层结构三、Condition源码解析3.1 newCondition()3.2 await() 总结主要方法&#xff1a; 回顾 如果你还没熟悉 AQS 中的独占锁&#xff0c;可以先看这篇文章的前导篇。上一篇文章是以ReentrantLock 里面的加锁、解…

【2024年华数杯C题老外游中国】(完整题解+代码+完整参考论文)

请问 352 个城市中所有 35200 个景点评分的最高分&#xff08;Best Score&#xff0c;简称 BS&#xff09;是多少&#xff1f;全国有多少个景点获评了这个最高评分&#xff08;BS&#xff09;&#xff1f;获评了这个最高评分&#xff08;BS&#xff09;景点最多的城市有哪些&am…

2024带你轻松玩转Parallels Desktop19虚拟机!让你在Mac电脑上运行Windows系统

大家好&#xff0c;今天我要给大家安利一款神奇的软件——Parallels Desktop 19虚拟机。这款软件不仅可以让你在Mac电脑上运行Windows系统&#xff0c;还能轻松切换两个操作系统之间的文件和应用程序&#xff0c;让你的工作效率翻倍&#xff01; 让我来介绍一下Parallels Desk…

【口语】基础英语之疑问句 | 描述一个认为音乐很重要的人

文章目录 一、基础英语之疑问句二、口语题&#xff1a;描述一个认为音乐很重要并且喜欢音乐的人 一、基础英语之疑问句 英语中的疑问句可以根据结构和用途被分为几种主要类型&#xff1a; 一般疑问句&#xff08;General Questions&#xff09;: 结构&#xff1a;助动词 主语…

Learn ComputeShader 03 Passing data to shader

这次我们想要在一个平面中生成随机运动的圆形。之前传递数据都是通过setInt&#xff0c;setVector等方法进行的&#xff0c;但是这些方法并不能一下传递大量数据&#xff0c;比如一个结构体数组&#xff0c;一个数据块。所以这次的主要内容就是通过buffer传递大量数据。 首先是…