函数的工作原理

递归函数工作原理 递归是一种较为特殊的算法,简单来说,“函数”(或者说子程序)不只是能够被其他函数调用(或者引用)的程序单元,在某些语言中函数提供了调用自己的功能,这种功能就是所谓的“递归”。递归的定义假如一个函数或者子程序是由自身所定义和调用的,就称为递归。递归至少要定义两种条件:一个是可以反复执行的递归过程,另一个是跳出执行过程的出口。递归的分类根据递归调用对象的不同,可以把递归分为以下两种: 1)直接递归:在 阅读详情

函数调用的工作流程  

  1. 传递参数:通过栈(_cdecl,_stdcall)或寄存器(_fastcall)。
  2. 函数调用:使用call指令调用函数,并将返回地址压入栈中。
  3. 保存栈底:将调用方的栈底寄存器ebp压栈。
  4. 申请栈空间,并保存寄存器环境:根据局部变量的多少提升esp(add esp,n)来开辟栈空间,用于存放函数的局部变量(VC6.0中debug模式这部分空间初始化为0XCC),并将函数中要用到的寄存器压栈进行保护。
  5. 函数实现代码
  6. 恢复寄存器环境:还原栈中保存的寄存器信息
  7. 平衡栈空间:平衡局部变量使用的栈空间,即进行降低esp操作(sub esp,n)。
  8. 函数返回:从栈顶取出第二步保存的返回地址
    • _cdecl调用方式,执行ret;相当于pop eip;(调用方平衡参数占用的栈空间)
    • 非_cdecl调用方式,执行ret n;相当于pop eip; add esp, n;(add esp,n 用于平衡参数占用的栈空间)

栈的形成和关闭

栈是内存中一段特殊的内存空间,后进先出原则。使用push、pop指令进行入栈、出栈操作。esp为栈顶寄存器,ebp为栈底寄存器,栈是向下生长的,即往地址低处生长。若栈非空,则esp指示的地址比ebp指示的地址小;若esp指示地址比ebp指示地址大,则为空栈。在VC6.0中,栈中可寻址的数据有局部变量、函数返回地址、函数参数等。当进行函数调用时,系统会开辟此函数所需的栈空间,而函数调用结束时,将释放开辟的栈空间,这一过程称为栈平衡。

函数调用方式说明

  1. _cdecl: C/C++默认的调用方式,调用方平衡函数参数所使用的栈空间。在函数返回后执行add esp, x(其中x为所有参数所占用栈空间大小,以字节为单位)
  2. _stdcall:被调方平衡函数参数所使用的栈空间,即在函数返回时使用ret n指令。不定参数的函数无法使用此种调用方式。
  3. _fastcall: 使用寄存器传递参数,只使用了ecx和edx,分别传递第一个和第二个参数(从左往右分别为第一个、第二个...),其他参数则用栈传递。此种方式调用效率最高。
  • _cdecl和_stdcall对比(VC6.0 Debug模式下)注意:在Release模式下_cdecl参数平衡时可能存在复写传播优化)
图(1)源码:_cdecl与_stdcall的对比——Debug模式
图(2) 上图源代码的反汇编代码
  • _fastcall调用方式(VC6.0 Debug模式下)
图(3) 源码 _fastcall示例
图(4)上图源代码的反汇编代码
如上所示,最后的ret 8语句便是被调用平衡参数所占用的栈空间。而在调用方call @ILT+15(ShowFast)(00401014)后不用平衡参数所用栈空间。

函数参数

    函数参数通过栈结构或寄存器进行传递,在C++代码中,传参顺序是自右向左依次入栈。参数也是函数中的变量。但与函数中局部变量的存放地址有些许不同。相对esp来说,局部变量存放地址偏移量为负数,而参数存放地址偏移量为正数。
    采用非引用形参,则push指令将形参复制到栈顶(即为实参的副本),与实参数据在两个不同的地址处,是独立存在的,因此对函数参数的修改,实际上是对当前保存在栈内参数中保存的值进行修改,与实参数据没有关系。所以说,在C/C++中,形参是实参的副本,对形参的修改不影响其实参。


函数返回值

    调用函数时,先将参数入栈,再执行call指令后,将返回地址压入栈中,调用完毕后执行ret指令,弹出返回地址到eip,并进行参数所用栈平衡操作。在VC中使用寄存器eax来保存返回值,若返回值大小打于4字节,则使用eax和edx来保存返回值。

TP-LINK电信定制摄像头刷机教程:解锁官方功能与固件升级 固件是嵌入式设备的操作系统,控制着硬件的基础功能。其工作原理是通过更新或替换存储在设备非易失性存储器中的程序代码,从而改变设备的行为和功能。这项技术的核心价值在于赋予用户对设备的完全控制权,能够解除厂商或运营商的软件限制,实现功能自定义、性能优化和安全更新。在智能家居、网络设备和物联网领域,固件升级与刷机是常见的工程实践,用于修复漏洞、增加新特性或适配不同平台。本文聚焦于利用TFTP恢复模式这一通用网络设备维护机制,针对TP-LINK电信定制版摄像头,提供一套完整的刷机方案,将设备刷入官方通用版固件,以解除 阅读详情

相关推荐

【BLE系列-第六篇】GATT解析:属性、特征、描述符的逻辑关系

本文系统介绍了BLE协议中的ATT和GATT机制。ATT以"属性"为基本数据单元,包含UUID、Handle、权限和Value四个要素。GATT则在ATT基础上构建了服务、特征和描述符的层次结构:服务(UUID:0x2800/0x2801)通过声明属性标识,特征声明(UUID:0x2803)指向特征值(UUID:0x2Axx或自定义),描述符(UUID:0x2900~0x290F)提供附加信息。GATT复用ATT发现机制,通过定义特定UUID语义实现服务发现和特征管理。这种设计使BLE设

qq_43399763的博客 1929

函数工作原理

*函数由多个部分组成:*1.函数名 函数名是函数开始地址的一个标签2.参数 函数的参数是给函数处理的资料,是函数中的变量。比如,在数学中,有个sine函数。如果你想让计算机计算2的正弦值,那么你可以调用函数名为sine的函数,以2为参数。另外,函数的参数可以有不止一个,甚至可以没有3.本地变量4.静态变量 静态变量是直到程序结束都一直有效的变量。函数内的静态变量对其他模

Dreamer的博客 1647

电影票购票小程序搭建(源码部署)

答:为用户提供便捷的购票方式,包括授权登录、个性化推荐、在线选座、订单管理等功能,同时在界面设计上注重用户友好性,简化用户的购票流程。答:通过展示电影院的优惠活动和票价信息,同时提供电影推荐功能,根据用户的历史购票记录和电影评分推荐个性化的电影列表,吸引用户购票。编写页面逻辑代码:使用JavaScript编写小程序页面的逻辑代码,实现电影列表的获取、电影详情的展示、座位选择的逻辑等。设计小程序界面:使用WXML和WXSS编写小程序的界面代码,实现电影列表的展示、电影详情的样式、座位选择页面的布局等。

2301_79072569的博客 2068

C++之类的成员函数的原理

先来一个类的成员函数的例子:#include<iostream>using namespace std;class MyTime { private: int hour; int minute; int second; public: void settime(int h, int m, int s) { hour = h; minut

maoliran的博客 1792

Zabbix-01简单导入MIB文件并测试

这里写自定义目录标题安装 MIB文件启用MIB文件测试MIB文件 MIB文件 MIB代表管理信息库。 MIB文件允许您使用OID(对象标识符)的文本表示。 ##例如: ifHCOutOctets 是OID【1.3.6.1.2.1.31.1.1.1.10】的文本表示 安装 MIB文件 在基于Debian的系统上: # apt install snmp-mibs-downloader # download-mibs 在基于RedHat的系统上: # yum install net-snmp-libs 启用M

lokibaba的博客 9178

别慌!Oracle MOS登录页面大变样?5分钟搞定新旧账号登录全流程

本文详细解析Oracle MOS登录页面改版后的新旧账号登录流程,帮助用户快速适应账号体系变革。针对传统MOS账号和OCI账号的不同应用场景,提供5分钟内完成无缝切换的实用指南,包括登录步骤、书签设置和密码管理策略,助力数据库管理用户高效访问Oracle技术支持资源。

weixin_30275415的博客 517

2021-04-23

第四天: 成员函数和普通函数的区别: 成员函数是面向对象的概念,所谓的成员函数,是指一个函数作为类的成员,公有成员、私有成员或者保护成员。 普通函数一般有两种传递方式,按类型传递和按值传递,也就是传指针和传返回值两种情况。成员函数一般是按类型传递,也即是传指针地址。 普通函数可以随便调用,并且无法继承和封装,成员函数根据类的不同,可以进行继承,根据公有私有的不同,调用方式也不同。 深层次的区别,普通函数作为C语言的概念,用的是stdlib,成员函数是用iostream,编译方法不同,至于谁占内存多,并不好

meng_1413的博客 346

Cadence PCB仿真使用Allegro PCB SI S参数配置方法图文教程

S参数即S-Parameter是指散射参数,描述信号在传输线中的正反向传输和正反向反射的情况。本文讲述在使用Allegro PCB SI进行信号完整性仿真前,S参数的配置方法。

fydar的博客 2177

C/C++中的函数参数传递机制

 一、 函数参数传递机制的基本理论   函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:值传递和引用传递。以下讨论称调用其他函数的函数为主调函数,被调用的函数为被调函数。   值传递(passl-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放

weiqiao00的专栏 525

GEE:基于自定义的年度时序数据集进行LandTrendr变化检测

本文介绍了使用年度时序数据进行LandTrendr变化检测的方法,包括核心函数调用、参数设置和结果可视化。通过筛选参数(年份、变化幅度和持续时间)对结果进行过滤,输出变化年份、变化幅度和持续时间。代码提供了完整的处理流程,包括数据输入、LandTrendr算法运行、结果筛选与可视化,并支持结果导出。适用于基于Google Earth Engine平台的地表变化检测分析。

养乐多的博客 752

Oracle EBS FA 如何打开关闭的资产会计期间?

用户“运行折旧”,误勾选为“关闭期间”,还有一部分资产还需要操作报废和调整,希望后台打开关闭的资产会计期。

陈显平的专栏-Oracle EBS 1030

析构函数的工作原理

如果对象是new出来的,那么它就是一个堆对象,不会被操作系统自动回收,需要我们手动调用delete函数释放该堆对象,在delete函数中会先调用析构函数释放该对象所申请的资源,那么析构函数如何释放对象所申请的资源呢,就是前面所说的,析构函数又会调用delete函数来释放对象所申请的资源,当然如果对象没有申请资源,那么就无需调用delete函数。

weixin_44049823的博客 2125

AI 智能体(Agent)应用开发工程师 · 进阶面试 (五)

在有多位 Agent 共同参与决策时(如评审委员会、代码审查小组),它们可能提出截然相反的建议。共识机制就是用来在这种冲突中得出唯一行动方案的规则。常用机制:多数投票:每个 Agent 一票,根据投票结果决定。实现简单,但忽略了专业度差异。加权投票:根据 Agent 的角色重要性或历史表现赋予不同权重,例如首席架构师 Agent 的票权重是普通开发者 Agent 的 2 倍。管理者仲裁:由一个权限更高的 Manager Agent 听取各方理由后做出最终裁决。这类似于层级制组织决策。辩论收敛。

篮球界最会写bug的人;程序猿中打球最菜的人。 393

变量和函数底层工作原理

变量和函数的底层工作原理涉及内存管理和指令执行。变量在编译期通过符号表记录类型和偏移量,运行时根据作用域分配到数据段、栈或堆中,通过地址计算访问。函数调用通过栈帧管理参数、返回地址和局部变量,执行call指令跳转至代码段,完成操作后通过ret返回。关键机制包括内存分段(代码段、数据段、栈、堆)和栈帧结构(由ebp和esp界定),实现程序的高效执行和内存访问。

Dd000110的博客 1096

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

C++中虚函数的作用和虚函数的工作原理

https://www.cnblogs.com/zkfopen/p/11061414.html

heart18335101121的博客 295

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

C语言基础 -- scanf函数的工作原理

在C语言中,输入主要是靠标准输入函数,也就是scanf函数来完成的。要正确的调用scanf函数来完成输入,需要了解scanf的工作原理。为了讲清楚原理,我先铺垫一下,介绍几个概念。(1)输入流:就是输入缓存区中从输入设备中输入的一系列字符。在我们个人电脑上,输入设备就是键盘,你从键盘上敲的一堆东西就是输入流。在PTA等刷题网站,实际上使用文件模拟了输入流,题目中的输入样例,还有测试点中的输入也是输入流。(2)匹配字符串:匹配字符串就是scanf函数调用时传入的第一个参数。也就是双引号里的那些字符。

LCCprogrammer 2476

Django视图函数的工作原理

Django视图函数的工作原理,HTML表单的一些基础机制,POST请求与GET请求的对比

2401_84561760的博客 470

C++虚函数的工作原理

静态绑定与动态绑定 讨论静态绑定与动态绑定,首先需要理解的是绑定,何为绑定?函数调用与函数本身的关联,以及成员访问与变量内存地址间的关系,称为绑定。 理解了绑定后再理解静态与动态。 静态绑定:指在程序编译过程中,把函数调用与响应调用所需的代码结合的过程,称为静态绑定。发生在编译期。 动态绑定:指在执行期间判断所引用对象的实际类型,根据实际的类型调用其相应的方法。程序运行过程中,把函数调...

weixin_30670925的博客 131

虚函数的工作原理

虚函数的工作原理:       编译器处理虚函数的方法:给每一个对象添加一个隐含的成员。隐含成员中保存了一个指向函数地址数组的指针。这个数组叫做 虚函数表(virtual function table) 1.假如一个类中有虚函数的话,对象的起始位就是虚函数表指针。虚表指针 2.基类   虚函数表中 存有所有虚函数的地址 3.派生类 包含有独立的虚函数表 (多继承有多个虚函数表,

精彩的艺术 549

C++ 虚函数与虚函数的工作原理

文章目录虚函数虚析构函数虚函数的工作原理获取对象的虚函数表地址 虚函数 给类函数声明virtual关键字,将该函数解释为虚函数。基类定义的虚函数表明子类可以继承并实现该虚函数。虚函数的最大作用为:可以通过基类指针或引用来接收一个子类指针或者引用,并通过基类指针或引用来调用虚函数来实现相同的动作不同的实现方式,达到多态的目的。 例子代码如下: #include <iostream> #include <string> using namespace std; class BaseC

白杨 920

函数调用 压栈的工作原理

   1.开篇   本篇文章着重写的是系统中栈的工作原理,以及函数调用过程中栈帧的产生与释放的过程,有可能名字过大,如果不合适我可以换一个名字,希望大家能够指正,小丁虚心求教!如果有哪里写的不清楚的或者错误的地方请及时更正,小丁再次谢过了。文章里面有错别字,也可能会有好友说寄存器的32、16位的区别其实我感觉这里主要讲的还是些原理性的东西,后续会将文章图片错别字进行调

u011555996的博客 2万+

构造函数的工作原理

构造函数的工作原理 首先,编写一个Duck类的构造函数。 function Duck(type,canFly){ this.type=type; this.canFly=canFly;g } 然后,用new关键字创建一个新的Duck对象 var fido=new Duck("white duck",false); 接下来详细说明一下构造函数的工作原理 new 首先创建了一个...

qq_43062639的博客 1294

笔试面试题3——虚函数的工作原理

3.虚函数的工作原理 详见::http://blog.youkuaiyun.com/hackbuteer1/article/details/7883531

WQP_Ya_Ping的博客 541
上一篇: 数据结构 绪论
下一篇: 结构体和类
Yangping_Peng
博客等级 码龄14年 0粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值