C++ C语言中的函数序言和结语
我知道嵌套函数调用中的数据会进入堆栈。当函数被调用或返回时,堆栈本身实现了一个逐步存储和从堆栈中检索数据的方法。这些方法的名称被称为序言和尾声 我试图搜索有关这个主题的资料,但没有成功。你们知道关于C语言中函数序言和尾声的工作原理的任何资源(网站、视频、文章)吗?或者如果你能解释的话会更好C++ C语言中的函数序言和结语,c++,c,assembly,stack-frame,epilogue,C++,C,Assembly,Stack Frame,Epilogue,我知道嵌套函数调用中的数据会进入堆栈。当函数被调用或返回时,堆栈本身实现了一个逐步存储和从堆栈中检索数据的方法。这些方法的名称被称为序言和尾声 我试图搜索有关这个主题的资料,但没有成功。你们知道关于C语言中函数序言和尾声的工作原理的任何资源(网站、视频、文章)吗?或者如果你能解释的话会更好 附言:我只是想了解一些一般情况,不要太详细。有很多资料可以解释这一点: (维基百科) (维基百科) (MSDN) 举几个例子 基本上,正如您所描述的,“堆栈”在程序的执行中有几个用途: 在调用函数时跟踪返
附言:我只是想了解一些一般情况,不要太详细。有很多资料可以解释这一点:
- (维基百科)
- (维基百科)
- (MSDN)
ebp
寄存器跟踪函数的堆栈帧。处理器使用esp
寄存器指向堆栈上最近添加的内容(最高值)。(在优化的代码中,使用ebp
作为帧指针是可选的;也可以使用其他方式展开异常堆栈,因此不需要花费指令来设置它。)
call
指令做两件事:首先将返回地址推送到堆栈上,然后跳转到被调用的函数。在调用之后,esp
立即指向堆栈上的返回地址。(因此,在函数输入时,设置了一个ret
可以执行,将返回地址弹出到EIP中。开场白将ESP指向其他地方,这也是我们需要结束语的部分原因。)
然后执行序言:
push-ebp;保存堆栈帧基指针(调用函数的)。
mov-ebp,esp;将堆栈帧基指针设置为当前值
; 堆栈上的位置。
亚esp,N;将堆栈增加N个字节,以便为局部变量保留空间
在这一点上,我们有:
。。。
ebp+4:返回地址
ebp+0:调用函数的旧ebp值
ebp-4:(局部变量)
...
结语:
mov-esp,ebp;将堆栈指针放回执行此函数时的位置
; 有人打电话来。
pop-ebp;还原调用函数的堆栈帧。
ret;返回到调用函数。
很好地解释了调用堆栈的概念
简要说明汇编代码以及如何和为什么
每个函数都有相同的序言(函数代码的开始)和尾声(函数的结束)
序言:序言的结构如下所示:
推ebp
电除尘器
结语:序言的结构如下:
离开
ret
更详细地说:我参加聚会已经很晚了&我相信在这个问题被问到的过去7年里,你会对事情有一个更清晰的理解,当然,如果你选择进一步追问这个问题的话。然而,我想我还是会尝试一下,尤其是序言和尾声中的“为什么”部分
此外,公认的答案优雅而简单地解释了尾声和序言的用法,并提供了很好的参考。我只想用为什么(至少是逻辑上的为什么)部分来补充这个答案
我将引用以下已被接受的答案,并尝试扩展其解释
在IA-32(x86)cdecl中,语言使用ebp寄存器来保持
跟踪函数的堆栈帧。esp寄存器由
processor指向上最近添加的值(最大值)
堆叠
call指令做两件事:首先它推送返回
地址,然后跳转到被调用的函数。
通话结束后,esp立即指向
堆叠
上面引用的最后一行在调用后立即显示,esp指向堆栈上的返回地址。
为什么?
因此,让我们假设当前正在执行的代码有以下情况,如下图所示(绘制得非常糟糕)
所以我们要执行的下一条指令是,比如地址2。这就是EIP指向的地方。当前指令有一个函数调用(它将在内部转换为汇编call
指令)
现在理想情况下,因为EIP指向下一条指令,所以这确实是下一条要执行的指令。但是,由于存在某种偏离当前执行流路径的情况(由于调用
,这是现在的预期),EIP的值将发生变化。为什么?因为现在可能需要执行另一条指令,可能在其他地方,比如在地址1234(或其他什么地方)。但是,为了按照程序员的意图完成程序的执行流,在转移活动完成后,控件必须返回地址2,因为如果没有发生转移,那么接下来应该执行地址2。让我们在正在进行的调用
的上下文中将此地址2称为返回地址
问题1
所以,在转移注意力之前