C语言函数调用详细过程

函数调用是步骤如下:

  1. 按照调用约定传参

    • 调用约定是调用方(Caller)和被调方(Callee)之间按相关标准

      对函数的某些行为做出是商议,其中包括下面内容:

      传参顺序:是从左往右传还是从右往左

      传参方式:是用寄存器传还是使用内存传

      平栈方式:是调用方平栈还是被调方平栈

      返回值的传递方式:是用寄存器传还是使用内存传

    • 什么是堆桟?

      一个程序运行的时候,它的进程的地址空间一般可以分为四块:

      代码区,数据区,堆,栈,每块功能如下:

      区域 功能
      代码区 存放函数被编译后的二进制可执行代码
      数据区 只读区:存放常量,例如:常量字符串,const修饰的全局变量等
      可读写区:存放全局变量和静态变量
      除去其他三个区域,剩下的都是堆,不连续
      存放函数运行时所需的参数,寄存器环境,返回值,局部变量

    以下面代码为例:

        int  TestFunction(char szBuff[],int nSize)
    {
    for (int iIndex = 0; iIndex < nSize; iIndex++)
    {
    szBuff[iIndex] = 'x';
    }
    return 3;
    } int main()
    {
    char szBuff[32] = { "sfjdlskfjl" };
    int nRet = TestFunction(szBuff, 32);
    return 0;
    }

    函数参数参数传递:



    从上图中可以看出函数参数入栈

  2. 保存返回地址(紧挨着被调用函数的下一行可执行代码的内存地址)

    从上图中可以看出函数调用完成后,紧挨着的第一条指令为:

    00EB175B add esp,8

    所以,参数传递完成后就是返回值入栈:

  3. 程序流程转移到被调用函数地址处

  4. 保存调用方栈底

  5. 切换到当前函数(被调用函数)的栈底

    调用方栈底保存完成后,当前的栈顶(ESP记录的地址)就成为被调用函数的栈底

  6. 为局部变量分配空间



    这里程序为调试版本,所以为局部变量分配的空间比较大,在Release版本中

    会根据局部变量实际所需空间来分配大小

  7. 保存寄存器环境

    这里一共保存了3个寄存器,共12字节,在Release版本下,只保存两个



    在Debug版程序中(有/Zi(带有调试信息)和/Od(禁止优化)编译命令),除了为

    局部变量分配较大的内存空间外,还会将分配的局部变量空间全部置为0xCC:



    这种填充方式比较直观,能够让我们在调试时直观的观察到是否发生越界等错误

  8. 开始执行函数体代码

    此时当前函数的栈的内存布局如下:

  9. 恢复寄存器环境

  10. 释放分配的局部变量空间

    只是将当前的栈底指针(EBP)的值赋值给栈顶指针(ESP)就完成了:

  11. 恢复调用方栈底

  12. 平栈或者返回

    • 如果是_fastcall,_stdcall调用约定,那么被调用函数平栈后,取出返回地址

      函数流程转移到调用方
    • 其他调用约定则是直接取出保存的返回地址,函数流程返回到调用方,又调用方

      平栈

C语言函数调用完整过程的更多相关文章

  1. C语言函数调用过程,汇编角度查看

    C语言函数调用过程,汇编角度查看 把函数的参数按照调用约定压栈或者存储到寄存器中 调用要使用的函数,先把调用者的地址入栈,方便回来 跳转到函数 把函数使用到的一些寄存器压栈,避免修改寄存器的值 执行函 ...

  2. C语言函数调用时候内存中栈的动态变化详细分析(彩图)

    版权声明:本文为博主原创文章,未经博主允许不得转载.欢迎联系我qq2488890051 https://blog.csdn.net/kangkanglhb88008/article/details/8 ...

  3. 字符型图片验证码识别完整过程及Python实现

    字符型图片验证码识别完整过程及Python实现 1   摘要 验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越 ...

  4. 测试c语言函数调用性能因素之测试三

    函数调用:即调用函数调用被调用函数,调用函数压栈,被调用函数执行,调用函数出栈,调用函数继续执行的一个看似简单的过程,系统底层却做了大量操作. 操作: 1,               调用函数帧指针 ...

  5. Django之model模块创建表完整过程

    Django中,与数据库相关的模块是model模块,它提供了一种简单易操作的API方式与数据库交互,它是通过ORM映射的方式来操作数据库,一个类对应数据库一张表,一个类属性,对应该表的一个字段,一个实 ...

  6. UIPickerView/UIDatePicker/程序启动的完整过程

    一.UIPickerView 1.UIPickerView的常见属性 数据源(用来告诉UIPickerView有多少列多少行) @property(nonatomic,assign) id<UI ...

  7. C语言函数调用栈

    C语言函数调用栈 栈溢出(stack overflow)是最常见的二进制漏洞,在介绍栈溢出之前,我们首先需要了解函数调用栈. 函数调用栈是一块连续的用来保存函数运行状态的内存区域,调用函数(calle ...

  8. StartSSL免费SSL证书申请和账户注册完整过程

    StartSSL算是比较早提供免费SSL证书的第三方提供商,我们可以免费申请且免费续期使用到有需要HTTPS网址的用户.关于网站使用SSL证书主要还是因为谷歌在向导说明中提到如果一个网站使用到SSL证 ...

  9. C语言的编译过程、安装gcc编译器以及设置环境变量

    以我对C语言编译过程的了解,我用了一点时间画了一个图,提供给大家参考一下,希望有些能对您的问题提上帮助. 前几天刚初步学习了C语言的编译过程,感触挺深的.在C语言中头文件其实起了一个很大的作用. 1. ...

随机推荐

  1. Linux 驱动框架---设备文件devfs

    设备文件系统 Linux引入了虚拟文件系统,从而使设备的访问可以像访问普通文件系统一样.因此在内核中描述打开文件的数据inode中的rdev成员用来记录设备文件对应到的设备号.设备文件也由一个对应的f ...

  2. Linux 驱动框架---驱动中的时间相关

    内核中的时间 Linux 系统内核对于时间的管理依赖于硬件,硬件按一定的周期产生中断,周期由内核的一个配置值HZ决定在系统启动时会将定时器配置为HZ值指定的频率产生中断:同时内核和维护一个64位(X8 ...

  3. C语言中函数的调用方式

    第一眼看到这样一个题目的我,心想除了如下的直接调用还能怎么调用呢? 1 void fun(void) 2 { 3 ...... 4 //你的代码 5 ..... 6 } 7 int main(void ...

  4. React Native for Windows + macOS

    React Native for Windows + macOS React Native 0.63 https://aka.ms/ReactNative https://microsoft.gith ...

  5. svn conflict & svn cleanup

    svn conflict & svn cleanup OK $ svn --help $ svn cleanup Tree Conflicts https://tortoisesvn.net/ ...

  6. js function arguments types

    js function arguments types https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functi ...

  7. SVG to GeoJSON

    SVG to GeoJSON GEOJSON https://geojson.org/ http://geojson.io/ https://github.com/mapbox/geojson.io/ ...

  8. sublime 使用过程中遇到的问题

    1.当我把鼠标放置在下图所示的class上几秒钟后,sublime就会在全局查找当前的class字符,这时sublime就会出现卡顿或无响应 解决方法: 点击preferences下的settings ...

  9. Java魔法类:Unsafe应用解析

    本文转载自Java魔法类:Unsafe应用解析 前言 Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别.不安全操作的方法,如直接访问系统内存资源.自主管理内存资源等,这些方法 ...

  10. RxHttp - 轻量级、可扩展、易使用、完美兼容MVVM、MVC架构的网络封装类库

    前言 RxHttp是基于RxJava2+Retrofit 2.9.0+OkHttp 4.9.0实现的轻量级,完美兼容MVVM架构的网络请求封装类库,小巧精致,简单易用,轻轻松松搞定网络请求. GitH ...