函数调用栈

本文详细解释了函数调用过程中的栈结构变化,包括参数、返回地址及EBP寄存器的作用。通过分析函数调用栈,可以追踪到任意层级函数的地址。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[color=#345286] 参考文章:[url=http://liyiwen.iteye.com/blog/345525]http://liyiwen.iteye.com/blog/345525[/url][/color]

[color=#FF0000] 1. 一个函数调用动作可分解为:零到多个 PUSH 指令(用于参数入栈),一个 CALL 指令。CALL 指令内部其实还暗含了一个将返回地址(即 CALL 指令下一条指令的地址)压栈的动作。[/color]
[color=#FF0000] 2. 几乎任何本地编译器都会在每个函数体之前插入类似如下指令:PUSH EBP; MOV EBP ESP; 即,在程序执行到一个函数的真正函数体时,已有以下数据顺序入栈:参数,返回地址,EBP。[/color]

[color=#345286] 函数调用的返回地址,正是调用指令 Call 的下一个指令的地址。那么,有了返回地址,就可以得到 Call 指令的位置了。有 Call 指令的位置又能干什么呢?Call 指令就是一个跳转指令,它可以让 [b]IP(instruction point)[/b] 指向要跳转的指令的地址,从那里开始执行。对于函数调用来说,就是让 IP 指向被调用的函数的地址。Call 指令的操作数其实和被调用函数的地址有非常重要的关系。有了 Call 指令的操作数,就可以计算出被调用函数的地址。[/color]

[color=#345286] 但仅仅有这个还不够。比如,A 调用了 B,那么在 A 函数中肯定有一个 Call 指令,但这个 Call 指令中的操作数是和 B 函数地址相关的,与 A 的函数地址直接关系不大(至少在没有其它信息的情况下,不能计算出 A 的地址)。而我们要得到的却是 A 函数的地址。所以,得向上再找一层,找到调用 A 函数的地方,那个地方的 Call 指令里的操作数才和 A 函数地址有关。也就是说,Z 函数调用了 A 函数,A 函数调用了 B 函数。现在要得到 A 函数的地址,我们得在 Z 函数里找 Call 指令的操作数。这时候 EBP 就派上用场了。本地编译器在每个函数体之前插入的指令(PUSH EBP; MOV EBP ESP)构造了一个巧妙的结构,使得我们可以顺着函数调用栈一层一层向上,找到所有调用关系。[/color]

[color=#345286] 如何向上查找呢?我们看看函数调用时栈、EBP 的值的情况就知道了。假设现在函数在正 Z 函数内执行,那么此时栈和 EBP 的值可能是像下图这样的:[/color]
[img]http://dl.iteye.com/upload/attachment/589245/5a98f2c1-3f7c-383c-9c7e-162ca41a3cab.jpg[/img]
[color=#345286] 我们先不管现在 EBP 指向的内存(0x000F)中的内容 XXX 是什么(要不然会是鸡生蛋生鸡的问题),总之目前在栈中的着色块中的内容是属于函数 Z 的参数,Z 执行结束后应该返回的地址以及 Z 函数的局部变量值。[/color]

[color=#345286] 现在 Z 函数调用 A 函数,会先将传给 A 的参数压栈,然后将现在这个指令(就是"Call A")的下一个指令的地址压入栈中,以便 A 函数完后返回到 Z 中继续执行。然后进入 A 函数的内存空间,首先就是调用 PUSH EBP,也就是将 Z 的 EPB 的内容(地址 0x000F)压入栈中,然后再 MOV EBP ESP,让 EBP 有一个新的栈顶(此时栈顶中的内容不就是 Z 函数时 EBP 的内容么?),然后再将 A 函数的局部变量压入栈中,开始执行 A 函数的代码。这时,栈和 EBP 的情况就像如图所示了:[/color]
[img]http://dl.iteye.com/upload/attachment/589248/a80b14d1-a44a-30b5-b127-beedee2a63d3.jpg[/img]
[color=#345286] 这样就很清楚了,原来现在的 EBP 中的内容,正是上一级函数的 EBP 中的内容。而每一个函数的 EBP 指向的位置,向栈顶可以得到该函数的局部变量,向栈底可以得到函数的返回地址和参数。于是我们就可以根据这个结构层层向上,找到任何一层我们想找的函数 EBP,从而也就能得到相应的返回地址了。[/color]
内容概要:本书《Deep Reinforcement Learning with Guaranteed Performance》探讨了基于李雅普诺夫方法的深度强化学习及其在非线性系统最优控制中的应用。书中提出了一种近似最优自适应控制方法,结合泰勒展开、神经网络、估计器设计及滑模控制思想,解决了不同场景下的跟踪控制问题。该方法不仅保证了性能指标的渐近收敛,还确保了跟踪误差的渐近收敛至零。此外,书中还涉及了执行器饱和、冗余解析等问题,并提出了新的冗余解析方法,验证了所提方法的有效性和优越性。 适合人群:研究生及以上学历的研究人员,特别是从事自适应/最优控制、机器人学和动态神经网络领域的学术界和工业界研究人员。 使用场景及目标:①研究非线性系统的最优控制问题,特别是在存在输入约束和系统动力学的情况下;②解决带有参数不确定性的线性和非线性系统的跟踪控制问题;③探索基于李雅普诺夫方法的深度强化学习在非线性系统控制中的应用;④设计和验证针对冗余机械臂的新型冗余解析方法。 其他说明:本书分为七章,每章内容相对独立,便于读者理解。书中不仅提供了理论分析,还通过实际应用(如欠驱动船舶、冗余机械臂)验证了所提方法的有效性。此外,作者鼓励读者通过仿真和实验进一步验证书中提出的理论和技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值