函数是任何一门高级语言中必须要存在的,使用函数式编程可以让程序可读性更高,充分发挥了模块化设计思想的精髓,今天我将带大家一起来探索函数的实现机理,探索编译器到底是如何对函数这个关键字进行实现的,并使用汇编语言模拟实现函数编程中的参数传递调用规范等。

说到函数我们必须要提起调用约定这个名词,而调用约定离不开栈的支持,栈在内存中是一块特殊的存储空间,遵循先进后出原则,使用push与pop指令对栈空间执行数据压入和弹出操作。栈结构在内存中占用一段连续存储空间,通过esp与ebp这两个栈指针寄存器来保存当前栈起始地址与结束地址,每4个字节保存一个数据。

一般编译器实现调用调用约定无外乎以下这几种:

  • CDECL:C/C++默认的调用约定,调用方平栈,不定参数的函数可以使用,参数通过堆栈传递.
  • STDCALL:被调方平栈,不定参数的函数无法使用,参数默认全部通过堆栈传递.
  • FASTCALL32:被调方平栈,不定参数的函数无法使用,前两个参数放入(ECX, EDX),剩下的参数压栈保存.
  • FASTCALL64:被调方平栈,不定参数的函数无法使用,前四个参数放入(RCX, RDX, R8, R9),剩下的参数压栈保存.
  • System V:类Linux系统默认约定,前八个参数放入(RDI,RSI, RDX, RCX, R8, R9),剩下的参数压栈保存.

当栈顶指针esp小于栈底指针ebp时,就形成了栈帧,栈帧中可以寻址的数据有局部变量,函数返回地址,函数参数等。不同的两次函数调用,所形成的栈帧也不相同,当由一个函数进入另一个函数时,就会针对调用的函数开辟出其所需的栈空间,形成此函数的独有栈帧,而当调用结束时,则清除掉它所使用的栈空间,关闭栈帧,该过程通俗的讲叫做栈平衡。而如果栈在使用结束后没有恢复或过度恢复,则会造成栈的上溢或下溢,给程序带来致命错误。

cdecl 调用者平栈: cdecl是C/C++默认调用约定,该调用方式在函数内不进行任何平衡参数操作,而是在退出函数后对esp执行加4操作,从而实现栈平衡。

该约定会采用复写传播优化,将每次参数平衡的操作进行归并,在函数结束后一次性平衡栈顶指针esp,且不定参数函数可使用此约定。

stdcall 被调用者平栈: stdcall与cdecl只在参数平衡上有所不同,其余部分都一样,但该约定不定参数函数无法使用。

cdecl调用方式的函数在同一作用域内多次被调用,会在效率上比stdcall高一些,因为它可以使用复写传播优化,而stdcall在函数内平衡栈,无法使用复写传播优化。

fastcall 被调用者平栈: fastcall效率最高,它可利用寄存器传递参数,一般前两个或前四个参数用寄存器传递,其余参数传递则转换为栈传递,此约定不定参数函数无法使用。

对于32位来说使用ecx,edx传递前两个参数,后面的用堆栈传递。

对于64位则会使用RCX,RDX,R8,R9传递前四个参数,后面的用堆栈传递。

使用esp寻址: 在O2编译器选项中,为了提高程序执行效率,只要栈顶是稳定的,就可以不再使用ebp指针,而是利用esp指针直接访问局部变量,这样可节省一个寄存器资源。

如下一段汇编代码,我们找到当前ESP基地址。

可以看到,esp+18就是第一个传入参数,那么程序在编译时,其实已经算出来了。

使用esp寻址后,不必每次进入函数后都调整栈底ebp,从而减少了ebp的使用,因此可以有效提升程序执行效率。

但每次访问都需要计算,如果在函数执行过程中esp发生了变化,再次访问变量就需要重新计算偏移了。

参考文献:《C++反汇编与逆向分析技术揭秘》

C++ 反汇编:关于函数调用约定的更多相关文章

  1. 【黑客免杀攻防】读书笔记7 - 软件逆向工程基础1(函数调用约定、Main函数查找)

    0x1 准备工作 1.1.准备工具 IDA:交互式反汇编工具 OllyDbg:用户层调试工具 Visual Studio:微软开发工具 1.2.基础知识 C++开发 汇编语言 0x2 查找真正的mai ...

  2. C语言函数调用约定

    在C语言中,假设我们有这样的一个函数: int function(int a,int b) 调用时只要用result = function(1,2)这样的方式就可以使用这个函数.但是,当高级语言被编译 ...

  3. Windows x64汇编函数调用约定

    最近在写一些字符串函数的优化,用到x64汇编,我也是第一次接触,故跟大家分享一下. x86:又名 x32 ,表示 Intel x86 架构,即 Intel 的32位 80386 汇编指令集. x64: ...

  4. 汇编  cdecl 函数调用约定,stdcall 函数调用约定

    知识点:  cdecl 函数调用约定  stdcall 函数调用约定  CALL堆栈平衡 配置属性--> c/c++ -->高级-->调用约定 一.cdecl调用约定 VC++ ...

  5. Microsoft函数调用约定

    Microsoft函数调用约定 对于所有调用共有的约定:ebx.ebp.esi.edi都是calle-save,即由被调用的函数负责它们的保存(如果被调用函数用到了这些寄存器的话) 先看函数调用发生了 ...

  6. 关于函数调用约定-thiscall调用约定

    函数调用约定描述了如何以正确的方式调用某些特定类型的函数.包括了函数参数在栈上的分配顺序.有哪些参数将通过寄存器传入,以及在函数返回时函数栈的回收方式等. 函数调用约定的几种类型 stdcall,cd ...

  7. C/C++函数调用约定与this指针

    关于 C/C++ 函数调用约定,大多数时候并不会影响程序逻辑,但遇到跨语言编程时,了解一下还是有好处的. VC 中默认调用是 __cdecl 方式,Windows API 使用 __stdcall 调 ...

  8. 函数调用约定_stdcall[转]

    关键字 清理堆栈 参数入栈顺序 函数名称修饰(C) __cdecl 调用函数 右 à 左 _函数名 __stdcall 被调用函数 右 à 左 _函数名@数字 __fastcall 被调用函数 右 à ...

  9. c++中的几种函数调用约定(转)

    C++中的函数调用约定(调用惯例)主要针对三个问题: 1.参数传递的方式(是否采用寄存器传递参数.采用哪个寄存器传递参数.参数压桟的顺序等): 参数的传递方式,最常见的是通过栈传递.函数的调用方将参数 ...

  10. 关于 C/C++ 函数调用约定

    关于 C/C++ 函数调用约定,大多数时候并不会影响程序逻辑,但遇到跨语言编程时,了解一下还是有好处的. VC 中默认调用是 __cdecl 方式,Windows API 使用 __stdcall 调 ...

随机推荐

  1. 怎样修改自己的登录shell

    问题 我只是Linux系统的普通用户,没有权限调用chsh命令修改自己的登录shell. bash-4.1$ chsh --help Usage: chsh [ -s shell ] [ --list ...

  2. linux 查看历史命令 history命令

    1.history命令 "history"命令就是历史记录.它显示了在终端中所执行过的所有命令的历史. history //显示终端执行过的命令 history 10 //显示最近 ...

  3. vim安装使用pathogen

    pathogen是什么? pathogen一般作为vim新手的第一个插件,用来统一管理vim插件包, (官方解释)非常容易的管理你的 'runtimepath' ,在实际项目中,vim-pathoge ...

  4. java 访问 太平洋网ip接口,解决前端js 跨域访问失败问题

    前端 js访问太平洋网IP接口地址,返回结果是403 服务器拒绝处理异常, 于是,想到了使用 服务器端访问,然后再将查询结果返回的前端 这是Java的测试源码,[具体的contronller端源码懒得 ...

  5. elasticsearch在linux上的安装,Centos7.X elasticsearch 7.6.2安装

    本文环境:Elasticsearch7.6.2目前最先版本   centos7.X     JDK1.8 elasticsearch介绍 官网:https://www.elastic.co/cn/pr ...

  6. weblogic 未授权命令执行漏洞(CVE-2020-14882,CVE-2020-14883)复现

    漏洞描述 2020年10月29日,360CERT监测发现 Weblogic ConSole HTTP 协议代码执行漏洞,该漏洞编号为 CVE-2020-14882,CVE-2020-14883 ,漏洞 ...

  7. sql多行合并一列

    with a as( select * from( select 1 userId , '天津' province union select 1 userId , '北京' union select ...

  8. 【刷题-LeetCode】154 Find Minimum in Rotated Sorted Array II

    Find Minimum in Rotated Sorted Array II Suppose an array sorted in ascending order is rotated at som ...

  9. unity3d发布安卓出错plese set the package name

    发布时报错 参考https://forum.unity.com/threads/where-is-package-name-setting.318839/ 参考https://answers.unit ...

  10. Cesium1.70-介绍CesiumOSM建筑新特性

    Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ 我们很高兴宣布Cesium OSM建筑,一个覆盖整个世界的3D建 ...