• C 函数实现原理


    0x00简介

    函数存储在栈上,栈从头到尾支持函数调用和传参,每个函数在栈上都有一席之地用来记录他的必要信息总结就是以下主要信息

    1.调用约定传参
    a 参数的传递方向
    b 参数的储存媒介
    c 谁负责释放参数空间
    d 返回值的处理
    调用者(caller)
    被调者(callee)
    _cdecl: 从右往左传递参数,参数通过栈传递,调用放负责清理参数空间(支持不定参)(c约定)
    _stdacll:从右往左传递参数,参数通过栈传递,被调用放负责清理参数空间(不支持不定参)
    _fastacall:从右往左传递参数,左数前两个参数通过处理器存放,其余参数通过栈保存,被调用放负责清理参数空间(不支持不定参)
    (微软某一个系列编译器约定)

    2.在栈顶保存放回地址
    3.保存调用方的栈信息
    4.更新栈位置被调用方的栈底处
    5.在栈内开辟局部变量的空间
    5a编译选项有/ZI+/0d 则同从局部变量空间为0xcc
    6 保存处理器环境
    7.执行函数体
    8.恢复处理器环境
    9.释放局部变量空间
    10.恢复栈信息到调用方
    11a __cdecl:取出返回地址,并按此流程更新,抵达新地址后,由调用方清理参数
    11b _stdacll,_fastacall 取出返回地址,并清理参数,让后按返回地址作流程更新

    0x01原理

    1.调用约定

    a.参数传递方向

    调用方去调用某个函数, 函数传递参数 这些都需要其他约定  不然就有分歧 传递传输是从左往右还是从右往左

    这些都是必要约定条件

    b.参数的传递方向

    提前约定不然就是 传递到栈 传递到寄存器,说白了就是参数的存储媒介问题

    c.谁负责释放参数空间

    当函数调用时 结束到底是谁来释放空间 是调用方还是被调用方

    d.返回值的处理

    约定返回值存放位置

    默认调用是

    c约定 国标约定_cdecl

    微软的系统上的约定_stdacll

    微软独家某一个系统约定的_fastacall

    跨平台首选_cdecl

    winapi 都是_stdacll

    _cdecl: 从右往左传递参数,参数通过栈传递,调用放负责清理参数空间(支持不定参)(c约定)
    _stdacll:从右往左传递参数,参数通过栈传递,被调用放负责清理参数空间(不支持不定参)
    _fastacall:从右往左传递参数,左数前两个参数通过处理器存放,其余参数通过栈保存,被调用放负责清理参数空间(不支持不定参)
    (微软某一个系列编译器约定)

    2.在栈顶保存放回地址

    在栈区中可以存放多个栈空间 

    top是做减法  每调用一个函数 top 减一 压入一个新的栈空间

     这是x86体系的方式 释放就是做加法

    通过栈低定位函数栈位置

    所以保留的栈信息就是栈低的

    3.保存调用方的栈信息

     4.更新栈位置被调用方的栈底处

    5.在栈内开辟局部变量的空间

    5a编译选项有/ZI+/0d 则填充局部变量空间为0xcc

    6 保存寄存器环境

    3个

    7.执行函数体

    8.恢复处理器环境

    9.释放局部变量空间
    10.恢复栈信息到调用方

    这里来看真实函数执行上面过程

    int test2(int x, int y)
    {
        int a = x + y;
        return a;
    }
    
    
    int test(int x, int y)
    {
      int a=test2(x,y);
      return a;
    }
    
    int  main()
    {
        
        int temp = 10;
        int temp1 = 5;
    
        test(10, 5);
        return 0;
    }

    那个01 00 00 00  标错了不是寄存器 应该是main的形参值 

    可以看到这个时候变量未初始化

     在main函数局部变量空间初始化了2个变量

     走进函数 压栈  3个寄存器存储信息   temp1和temp参数传入  

     在继续走

    和上面一样的

    从此山高路远,纵马扬鞭。愿往后旅途,三冬暖,春不寒,天黑有灯,下雨有伞。此生尽兴,不负勇往。
  • 相关阅读:
    unity3d 免费好用的数据库处理框架 数据库直连框架
    为.NET搭建Linux的开发环境,鄙视那些将简单事情复杂化的人
    为Linux重新开发MVC,有图有真相
    让我们一起用开源数据库和开源框架废弃Access
    C#子线程执行完后,调用主线程的方法
    javascript 将 table 导出 Excel ,可跨行跨列
    Easyui中 messager.alert 后某文本框获得焦点
    Easyui中 alert 带回调函数的 消息框
    wamp 在本地安装PHP环境, 开启 curl 扩展
    H+ 编辑tab页 保存后 刷新列表tab页 并关闭自已。tabA页调用tabB页的方法
  • 原文地址:https://www.cnblogs.com/feizianquan/p/14673520.html
Copyright © 2020-2023  润新知