一、基本概念

想要彻底的理解函数调用过程,先要明白一下几个概念。

1、栈

这里说的栈不是数据结构中的栈,而是计算机内存中的一块存储区,它的访问方式是“先进后出”。大多数情况下,栈是从高地址向低地址增长的。

栈有很多单元格,通常情况下每个单元格是8位的(即可以存8个0或1),称为数据宽度,是用来存放数据的。每个单元格都会对应一个地址,地址一般是无符号32位的整数,因此可以表示4294967295(32位无符号整数可以表示的最大值)个单元格。

关于栈的操作涉及到两个寄存器,即ESP和EBP(什么是寄存器这里就不多说了),另外还有两个指令,POP和PUSH。

首先说一下两个寄存器,这两个寄存器分别称为栈指针寄存器和基址指针寄存器,因此这两个寄存器中存的是指针,即地址(这个地址就是前面说到的单元格对应的地址),更确切的说应该是栈帧顶部的地址(ESP)和栈帧底部的地址(EBP)(栈帧是什么后面会讲到)。

下面是一个栈的结构图:

可以看到,栈是从高地址向低地址增长的,高地址对应栈底,低地址对应栈顶,每个存放数据的单元格都有一个对应的地址,每个单元格的宽度为8位。

下面说一下POP和PUSH指令,这两个指令都只能操作栈顶,PUSH是向栈中推入一个数放在栈顶,POP是将栈顶的数据弹出。无论是推入新的数据还是弹出数据,ESP始终指向栈顶,也就意味着ESP会不断改变。

注意到上面我写了个栈帧,下面解释一下栈帧是什么。

2、栈帧

栈帧是一块连续的栈区(注意看上面的图),每个函数都有自己的栈区,这个栈区就称为栈帧。注意,函数调用所占用的栈区才称为栈帧,并且每个函数都会有自己的栈帧,包括main函数。当前栈帧的范围在EBP和ESP指向的区域之间。

当然栈帧不是固定不变的,由于推入新的数据和弹出数据ESP都会改变,因此栈帧的大小也会随之改变,但是EBP一般不会改变。

那么什么时候会改变EBP?

前面说到,每个函数都有自己的栈帧,也就是有自己的EBP和ESP,那么当一个函数调用另外一个函数的时候,第二个函数也应该有自己的栈帧,也有自己的EBP和ESP,但是系统中只有一个相应的寄存器(即只有一个ESP寄存器和一个EBP寄存器)。因此这个时候就要改变EBP的值,在改变EBP的值之前把旧的EBP的值保存一下就可以了(这个后面还会讲到)。

3、保存寄存器

为什么要保存寄存器?

首先,寄存器数量有限,因此寄存器是被所有的函数共享的。假设现在有A、B两个函数,A函数调用了B函数。A在调用过程中往EAX中存放了数据x,B在调用过程中往EAX存放了新的数据y,那么当B函数调用结束返回到A函数后,A继续使用EAX中的值,但这个时候EAX中的值已经不是最初存的x了。

怎么保护?

方法很简单,在B函数使用EAX寄存器之前,在准备阶段(刚进入B函数时)先将寄存器中的值保存到栈中,用完以后,在结束阶段再从栈中将值重新写入EAX中。

注:并不是所有通用寄存器中的值都由被调用函数保存,通常调用函数保存一部分,被调用函数保存一部分。IA-32规定,寄存器EAX、ECX、EDX是调用者保存寄存器,寄存器EBX、ESI、EDI是被调用者保存寄存器。

二、函数调用大体流程

假设有两个函数A和B,A函数调用B函数,调用B函数需要传入两个参数x和y。

1:在A调用B函数之前,A先把需要传入B函数中的参数x,y推入栈中。(注意x,y被放在了A的栈帧中)

注:上面一句步骤没有说先把调用者保存寄存器推入栈中,事实上并不是每次调用函数都要把调用者保存寄存器推入栈中,只有在必要的时候才会进行保护(编译器自己决定)。

2:在执行函数调用的时候(即执行call指令),A把B函数的返回地址推入栈中(还是在A的栈帧中)。

3:在进入B函数后,推入旧的EBP的值,这时ESP指向的单元格中的内容是旧的EBP,然后令EBP等于当前的ESP,则这个EBP即为B函数的栈帧的栈底,EBP指向的单元格中的数据是旧的EBP。这里比较抽象,下面有一个图可以帮助理解。

(上图有个地方写错了,EBP应该是B函数栈帧的栈底)

4:开辟一块相对合适的空间用来存放非静态局部变量(存放非静态局部变量前会先置成cc)。

5:将被调用者保存寄存器中的内容推入栈中进行保护。

6:执行函数中的内容。

7:函数调用完毕,return。返回的时候将EDI、ESI、EBX依次弹出,然后让ESP指向EBP,将ESP指向的单元格中的内容(即旧的EBP)弹到EBP中,这样EBP又重新变成了A的栈帧的栈底,执行ret指令,弹出B的返回地址,然后ESP根据参数的个数加上相应的数使ESP指向原来A的栈帧的栈顶(一个参数加4,两个加8,以此类推)。这里有一点需要注意,ESP的值虽然改变了,但是栈中B的参数还存在,但是无所谓,在推入新的数据的时候就会被覆盖掉。

注意上图ESP = ESP+8后ESP指向了原来A栈帧的栈顶,但是B的参数还存在,不过当有新数据进来的时候就会被覆盖掉。

这里有个问题,B函数的参数在A函数的栈帧中,B函数应该怎么去读取使用呢?

注意推入参数和函数返回地址后就改变了EBP,因此EBP和函数的参数紧挨着(也就是说参数在B能够访问到的地方),那么怎么去访问呢?拿上面的例子讲,参数x在EBP+8中,参数y在EBP+12中。

博主最近比较忙,最后三部分抽时间再更。

三、用VC++6.0查看反汇编详解函数调用


四、用VC++6.0调试讲解函数递归调用


五、微软的内存保护机制


函数调用的汇编语言详解相关推荐

  1. 看雪学院课程《汇编语言详解与二进制漏洞初阶》笔记

    前言和声明 安全工程师这条路任重道远.如今国际形势复杂,网络战一旦爆发,安全势力弱的一方很快会处于竞争的下风,加上国家的安全人才缺口过大,我辈则应当肩挑重担,为祖国安全尽一份力. 本博客是博主在学习看 ...

  2. Python函数(函数定义、函数调用)用法详解

    函数 函数就是一段封装好的,可以重复使用的代码,它使得我们的程序更加模块化,不需要编写大量重复的代码. 函数可以提前保存起来,并给它起一个独一无二的名字,只要知道它的名字就能使用这段代码.函数还可以接 ...

  3. lua 函数调用1 -- 闭包详解和C调用

    这里, 简单的记录一下lua中闭包的知识和C闭包调用 前提知识: 在lua api小记2中已经分析了lua中值的结构, 是一个 TValue{value, tt}组合, 如果有疑问, 可以去看一下 一 ...

  4. 栈中函数调用原理_详解

                 函数调用是程序设计中的重要环节,本文就函数调用的过程进行分析. 一.eip.ebp.esp介绍 EIP,EBP,ESP都是系统的寄存器,里面存储的是些地址,我们系统中栈的 ...

  5. 函数调用过程实例详解

    原文标题:<函数调用过程探究> 引言 如何定义函数.调用函数,是每个程序员学习编程的入门课.调用函数(caller)向被调函数(callee)传入参数,被调函数返回结果,看似简单的过程,其 ...

  6. python函数定义及调用-Python函数(函数定义、函数调用)用法详解

    Python 中函数的应用非常广泛,前面章节中我们已经接触过多个函数,比如 input() .print().range().len() 函数等等,这些都是 Python 的内置函数,可以直接使用. ...

  7. php 命名空间 函数调用,PHP 命名空间 namespace 函数调用 类引用 详解

    PHP namespace 命名空间 函数调用 类引用 详细测试分析 本文测试中,假设index.php页面和test.php页面在同一个根目录下,方便加载test.php页面. 前提条件都是在nam ...

  8. python函数定义的语法形式_Python函数(函数定义、函数调用)使用详解

    函数是 Python 程序的重要组成单位,一个 Python 程序可以由很多个函数组成.前面我们己经用过大量函数,如 len().max() 等,使用函数是真正开始编程的第一步. 比如在程序中定义了一 ...

  9. C++函数调用栈分布详解

    VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从 ...

最新文章

  1. 机器学习Python实践》——数据导入(CSV)
  2. audio type多种类型_http content-type常见文件格式类型
  3. oracle imp 00028,oracle中导入.dmp文件时出现IMP-00009 和IMP-00028异常提示
  4. SAP 开发陷阱一箩筐(01)——创建了函数组却无法激活
  5. HP ALM 使用经验
  6. Linux进程状态解析
  7. Java并发编程—什么是线程?
  8. SAP成都研究院数字创新空间基于SAP C4C开发的一个智能服务原型项目
  9. openai-gpt_GPT-3报告存在的问题
  10. rmi java 服务_javaweb项目启动时自动启动rmi服务器实例
  11. 计算机基础试题及答案 完整版,大学计算机基础试题及答案(完整版)
  12. 云购系统、一元云购系统接入短信验证及订单通知功能
  13. 大数据与个人隐私的平衡:懂你,但不认识你
  14. 雷神 911X 猎荒者评测
  15. 第十届泰迪杯数据挖掘B题:电力系统负荷预测分析--解题思路与部分代码03
  16. 不用写采集规则也可以轻松采集网站文章,揭秘一款明泽文章采集软件的工作原理
  17. Kubernetes 进阶训练营 控制器
  18. WhatsApp 电脑版如何下载安装?
  19. SQL 万能本地文件分析工具
  20. 基于ssm的生活故事分享交流博客系统

热门文章

  1. 睡前1分钟 坚持瘦下来(信不信由你)
  2. [转载] python中list与string的转换
  3. [转载] Numpy数组对象ndarray
  4. Java之戳中痛点 - (5)switch语句break不能忘以及default不同位置的用法
  5. mysql Substr与char_length函数的应用
  6. ural 1012K-based Numbers. Version 2 1013. K-based Numbers. Version 3
  7. gnuplot 常用命令大全
  8. ROS 启动自带摄像头或者USB摄像头
  9. c语言教程 define,C语言中define的用法
  10. torch summary_留学论文如何5分钟搞定写作Summary,速看!