首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

5.5 汇编语言:函数调用约定

结构在内存中占用一段连续存储空间,通过espebp这两个指针寄存器来保存当前起始地址与结束地址,每4个字节保存一个数据。...当顶指针esp小于底指针ebp时,就形成了帧,帧中可以寻址的数据有局部变量,函数返回地址,函数参数等。...不同的两次函数调用,所形成的帧也不相同,当由一个函数进入另一个函数时,就会针对调用的函数开辟出其所需的空间,形成此函数的独有帧,而当调用结束时,则清除掉它所使用的空间,关闭帧,该过程通俗的讲叫做平衡...这种调用方式规定函数调用者在将参数压入中后,再将控制权转移到被调用函数,被调用函数通过顶指针ESP来访问这些参数。函数返回时,由调用者程序负责将堆栈平衡清除。...该调用方式在函数内不进行任何平衡参数操作,而是在退出函数后对esp执行加4操作,从而实现平衡。

21920

实例分析C程序运行时的内存结构

EBP顶初始值为0018FF84h,ESP初始为0018FF48h ESPEBP中的作用 在每个函数最开始的地方有两条语句 push ebp mov  ebp,esp 在函数返回前也有两条语句...mov esp,ebp pop ebp 每运行一个函数就新开一段空间,所谓的开空间就是移动ebp底,在移动ebp之前,通过push ebp保存上一级函数的底,然后用ebp指向现在函数顶,即为当前函数开辟了...;接着给局部变量进行地址分配以及保存现场等,esp不断向低地址移动,当函数调用结束时,esp指回当前函数的顶(mov esp,ebp),然后上一级函数的顶地址出保存在ebp中(pop ebp)。.../ ebp保存顶0,ebp=esp=0018FF44h 00401023   sub         esp,48h                    // esp -= 48h开辟了一段空间,...// ebp恢复为0018FF44h 004010C1   ret                                    // 返回,等待执行函数调用的下一条指令 在调用fun函数之前,

1K10
您找到你想要的搜索结果了吗?
是的
没有找到

恶意样本对抗回溯检测机制的套路浅析

push ebp ; 先将属于调用函数的 EBP 值压,执行后 ESP 指向地址存储该 EBP 的值 mov ebp, esp ; 将 ESP 的值赋给 EBP 寄存器,执行后 EBP 指向地址存储属于调用函数的...EBP 始终保持不变 mov esp, ebp ; 将 EBP 的值赋给 ESP 寄存器,执行后 ESP 指向地址存储属于调用函数的 EBP 的值 pop ebp ; 弹出保存在中的调用函数的...根据上面帧结构和 CALL 指令的操作可知,在将属于调用函数的 EBP 的值压之前,ESP 指向的地址存储的是由 CALL 指令压调用函数中调用位置的下一条指令的地址(原 EIP)。...下面的代码片段实现了分配新的缓冲区,并拷贝从 ESP 指针指向位置到 调用函数的 EBP中存储位置加上调用函数的返回地址的存储位置这个范围的片段,到新分配的缓冲区中最高位置区域,为低内存预留了...delta = p_ebp - p_esp; // 获取调用者的 EBP中的位置 if (p_esp > stacklimit && p_esp < stackbase

67020

函数调用过程(帧)

开发环境 Ubuntu 14.04(32bits) GCC 编辑器 Cmd Markdown 画图工具 Processon 1,函数调用过程 今天先介绍下基本的函数调用过程,即帧。...1.1帧 每个函数调用都对应一个帧。每个帧由ESPEBP寄存器来确定。每个函数执行时,其局部变量都是在自己对应的帧内分配内存。...//将ebp,即old ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp //ebp=esp .cfi_def_cfa_register...5 andl $-16, %esp //esp=esp&0xFFFFFFF0,即保证esp的最低4位为0 subl $32, %esp //向低地址生长,esp-=32 movl $10...//将变量i的值压 call test //调用test函数,其中将下条指令(即movl %eax, 28(%esp))\ 的地址压,即ret addr,然后转到test函数执行,即eip=test

79420

通过一篇文章让你了解什么是函数

当一个函数被调用时,它的局部变量和函数参数等信息会被压入中。ESP寄存器指向顶的地址,即最后被压入的数据所在的内存地址。使用ESP寄存器,可以轻松地在上分配和释放内存。...总之,ESP寄存器在x86架构中用于指向当前顶的地址,可以方便地进行函数调用操作。...每一次函数调用,都要为本次函数调用开辟空间,就是函数帧的空间。 这块空间的维护是使用了2个寄存器: espebpebp 记录的是底的地址, esp 记录的是顶的地址。...esp,0E4h //sub会让esp中的地址减去一个16进制数字0xe4,产生新的esp,此时的esp是main函数帧的esp,此时结合上一条指令的ebp和当前的espebp和...将main函数的 ebp 计算新的 ebpesp 将 ebx , esi , edi 寄存器的值保存 计算求和,在计算求和的时候,我们是通过 ebp 中的地址进行偏移访问到了函数调用前压进去的参数

9810

5.5 汇编语言:函数调用约定

顶指针esp小于底指针ebp时,就形成了帧,帧中可以寻址的数据有局部变量,函数返回地址,函数参数等。...不同的两次函数调用,所形成的帧也不相同,当由一个函数进入另一个函数时,就会针对调用的函数开辟出其所需的空间,形成此函数的独有帧,而当调用结束时,则清除掉它所使用的空间,关闭帧,该过程通俗的讲叫做平衡...; 保存底指针ebp mov ebp,esp ; 调整当前底指针到顶 sub esp,0e4h...这种调用方式规定函数调用者在将参数压入中后,再将控制权转移到被调用函数,被调用函数通过顶指针ESP来访问这些参数。函数返回时,由调用者程序负责将堆栈平衡清除。...该调用方式在函数内不进行任何平衡参数操作,而是在退出函数后对esp执行加4操作,从而实现平衡。

22020

C语言——F函数的帧的创建和销毁

相关汇编命令 mov:数据转移指令 push:数据入,同时esp顶寄存器也要发生改变 pop:数据弹出至指定位置,同时esp顶寄存器也要发生改变 sub:减法命令 add:加法命令 call:函数调用...2、这块空间的维护是使用了2个寄存器: espebpebp 记录的是底的地址, esp 记录的是顶的地址。 3、函数帧的创建和销毁过程,在不同的编译器上实现的方法大同小异。...mov ecx,dword ptr [ebp-8] //传递a,将ebp-8处放的10放在ecx寄存器中 00BE1857 push ecx //将ecx的值压esp-4 //跳转调用函数...//在顶弹出一个值,存放到ebx中,esp+4 00BE1782 mov esp,ebp //再将Add函数的ebp的值赋值给esp,相当于回收了Add函数的帧空间 00BE1784 pop ebp...//弹出顶的值存放到ebp顶此时的值恰好就是main函数的ebpesp+4,此时恢复了main函数的帧维护,esp指向main函数帧的顶,ebp指向了main函数帧的底。

7110

指针&& 帧指针详解

所以任何函数调用进来的第一件事都是保护调用者的帧指针,以使得返回时可以恢复调用者的帧指针,即pushl %ebp movl %esp %ebp有了上面这两个命令,函数就可返回了,返回时只要leave...在函数执行过程中,指针esp会随着数据的入和出而移动,因此函数中对大部分数据的访问都基于帧指针%ebp进行。?对于函数A调用函数B的情况,传递给B的参数包含在A的帧中。...(执行完此指令后,指针esp会向下移动,指向保存原ebp的空间的地方)4 movl %esp,%ebp (把数据(原ebp的值)压入后,指针esp会向下移动4个字节指向放原ebp的值的空间,执行此句指令的意义就...是把esp指向的地址赋值给%ebp,%ebp作为新:_swap底指针或者说是新的帧指针ebp使用)5 subl $4,%esp # 为局部变量c在内分配空间。...)的地址传送给寄存器%eax,此时 帧指针esp指向了-12%ebp处)25 pushl %eax # 作为调用的参数并压入中。

7.6K30

图解函数调用过程

在系统中程序执行的时候都是从高地址往低地址增长的 函数参数压,一般从右向左压(比如__cdecl函数调用约定) EIP寄存器存储当前执行指令的内存位置 EBP寄存器表明当前帧的ESP寄存器表明当前帧的顶...push ebp 步骤2.2 修改底,将当前ESP设置为EBP,切换到当前函数FunAdd的帧。...mov ebp,esp 步骤2.3 将ESP减去8,即增长8个字节(记住是从高地址往低地址增长的)这个操作就等于在上申请了8个字节的空间,为什么是8个字节呢?...mov esp,ebp pop ebp 步骤2.9 此时的ESP指向的值正是在第一步中保存的Return Address,即FunAdd调用后的下一条指令。...add esp,8 mov dword ptr [ebp-0Ch],eax 首先调用add esp, 8即将顶去除八个字节,而这8个字节正是用来存储FunAdd入参数的。

2.1K71

C语言:底层剖析——函数帧的创建和销毁

2、这块空间的维护是使用了两个寄存器:espebp(也可以理解成两个指针),ebp记录的是底的地址,esp记录的是顶的地址,而这两个地址就是用来维护函数帧的。...2.mov    ebpesp  move指令会把esp的值存放带ebp中,相当于产生了main函数的ebp,这个值就是invoke_main函数帧的esp。...相当于回收了Add函数的帧空间 pop         ebp       弹出顶的值存放到ebp顶此时的值恰好就是main函数的ebpesp+4,此时恢复了main函数的帧维护,esp...因为esp顶寄存器)和ebp底寄存器)用来维护函数的帧,他会根据调用函数的不同去向不同的位置,由于区的使用习惯时从高地址指向低地址,那么当Add函数执行完后想要回到main函数,此时Add的...ebp恰好就可以是main函数的esp,但是main函数的ebp此时已经不知道在哪里了,为了避免这种情况,创建Add函数帧的时候,espebp在变化维护的帧空间之前,会记录原来空间的底地址也就是

19310

汇编角度看函数堆栈调用

esp:专门用作堆栈指针,被形象的称为顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,esp就越来越小。在32位平台上,esp每次减少4个字节。 ebp:堆栈的底指针。...开始分析函数帧开辟的过程: 00401060 push ebp 00401061 mov ebp,esp 00401063 sub esp,4Ch...2.0040104E mov esp,ebp使得被调用函数帧回退。此时帧空间的内容还存在。 3.pop ebp 两个动作,出,并将出的值赋给ebp。...esp,8 相当于esp = esp + 8,是主函数压实参的帧回退。...答: (1)形参的内存空间的开辟和清理是由调用方执行的。 (2)主函数调用函数后执行执行调用之后的代码,是因为调用方在进行调用的过程中,将下一行指令的地址压

58320

【C语言】函数——帧的创建和销毁

每一次函数调用,都要为本次函数调用开辟空间,就是函数帧的空间。 2.这块空间的维护是使用了2个寄存器: espebpebp 记录的是底的地址, esp 记录的是顶的地址。...mov ecx,dword ptr [ebp-8] //传递a,将ebp-8处放的3放在ecx寄存器中 00BE1857 push ecx //将ecx的值压esp-4 //跳转调用函数 00BE1858...ebp-8处放的3放在ecx寄存器中 00BE1857 push ecx //将ecx的值压esp-4 //跳转调用函数 00BE1858 call 00BE10B4 00BE185D add esp...esp,8 00BE1860 mov dword ptr [ebp-20h],eax call 指令是要执行函数调用逻辑的,在执行call指令之前先会把call指令的下一条指令的地址进行压 操作,这个操作是为了解决当函数调用结束后要回到...将main函数的 ebp 计算新的 ebpesp 将 ebx , esi , edi 寄存器的值保存 计算求和,在计算求和的时候,我们是通过 ebp 中的地址进行偏移访问到了函数调用前压进去的

50610

【内功修炼】深入理解函数帧的创建和销毁

我们的程序中正在调用哪个函数,ebpesp维护的就是哪个函数的帧。...是的,ebpesp新维护的这块空间其实就是给main函数开辟的空间,也就是main函数的帧 所以,我们上面也提到:我们的程序中正在调用哪个函数,ebpesp维护的就是哪个函数的帧...总结一下: sub会让esp中的地址减去一个16进制数字0xe4,产生新的esp,此时新的esp就是main函数帧的esp,此时结合上一条指令的ebp和当前的espebpesp之间维护了一块新的空间...那我们还是来带大家简单分析一下: 首先呢又是 push ebp 把此时的ebp的值压 然后mov ebp,esp 之前ebp是在维护main函数的帧 那现在mov ebp,espesp...那就变成这样了 我们发现此时ebpesp又重新维护起了main函数的帧,这当然没问题,因为此时Add函数已经调用结束,就要回到main函数了。

10010

从汇编角度来理解linux下多层函数调用堆栈运行状态

esp寄存器总是指向顶,在x86平台上这个是从高地址向低地址增长的,我们知道每次调用一个函数都要分配一个帧来保存参数和局部变量,现在我们详细分析这些数据在空间的布局,根据gdb的输出结果图示如下...call   80483f2  要调用函数foo先要把参数准备好,第二个参数保存在esp+4指向的内存位置,第一个参数保存在esp指向的内存位置,可见参数是从右向左依次压的。...在每个函数的帧中,ebp指向底,而esp指向顶,在函数执行过程中esp随着压和出操作随时变化,而ebp是不动的,函数的参数和局部变量都是通过ebp的值加上一个偏移量来访问,例如foo函数的参数...现在esp所指向的顶保存着foo函数帧的ebp,把这个值恢复给ebp,同时esp增加4,esp的值变成0xbffff68c。 最后是ret指令,它是call指令的逆操作: 1....注意函数调用和返回过程中的这些规则: 1. 参数压传递,并且是从右向左依次压。 2. ebp总是指向当前帧的底。 3. 返回值通过eax寄存器传递。

92020

函数帧的创建与销毁

顶和底都有指针,顶指针是esp底指针是ebp,即esp指向顶,ebp指向底。...在32位平台上,ESP每次减少4字节。 其中EBPESP需要重点了解一下。 二、函数帧介绍 每个函数被调用时都会建立帧,在接下来的调试过程中我将会进一步解释。...,ebp //把ebp的值赋值给esp,即esp指向ebp的地址 00E913F6 pop ebp //把ebp中弹出(删除) 00E913F7 ret //ADD函数调用结束返回...main函数 00E91450 add esp,8 //给esp+8,也就是让esp底方向移动8个字节(因为我们把两个存着双字变量的值的寄存器eax和ecx也压入了,现在函数调用结束...00E91485 pop ebp //把ebp中弹出(删除) 00E91486 ret 三、小彩蛋 main函数可以调用别的函数,它自己也是可以被调用的。

48420

函数帧的创建和销毁介绍

首先理解一下寄存器: eax,ebx,ecx,edx,ebpesp。画横线的这两个寄存器存放的是地址。这两个地址是用来维护函数帧的。 每一次函数调用,都要在区创立一个空间。 什么是?...编写代码 详细解释帧创立和销毁过程 如下图所示,在区(计算机专门的内存空间),每个函数在区申请一块内存空间,称为函数帧。在调用哪个函数,espebp就跑去维护哪个函数的帧。...espebp首先维护main函数,再调用add函数。 此时ebpesp维护的是这样一个空间。进入main函数的第一步是push。push压里面放的是ebp。...当push完成之后,esp指到顶。 我们也可以在监视中观察到:1 2 我们可以观察到esp的地址 减少了4,意味着esp往上了4位。 接着执行move,move是把esp的值给ebp。...ebp的地址存在main函数当中,就是要让随着函数调用返回之后,随着帧的销毁,顶是很容易找到的,但是底不容易找到。pop弹出,ebp走了。 ebp就回回去了。

9110

C语言函数的帧详解

3.1 main函数帧创建 ​ 根据VS2013编译器调试,调用堆栈,不难发现main函数的调用链条如下: 很显然main函数在被调用时,创建了帧。...在调试过程中将转到反汇编,便能直观的看到main函数帧创建的过程。首先需明确的是,函数帧由寄存器esp,ebp维护。...,如图所示esp指向ebpebp成功压入中。...2.esp值传递给ebp。 3.esp减去0E4h:由于先使用高地址后使用低地址,减去一个值意味着esp指针向低地址移动了0E4h个地址,此处便开辟了main函数的帧。...,ebx,随后将ebp赋给esp并弹出ebp,最后执行ret指令返回到调用Add函数的call指令的下一地址,在执行ret指令时实际已弹出After call,以执行指令 add esp,8,此时esp

1.9K20

你知道函数帧的创建和销毁吗?

指针寄存器,存放函数顶地址 ebp 帧指针寄存器,存放函数底地址 espebp这两个寄存器中存放的是地址,这两个地址是用来维护函数帧的 在本节中,主要了解这俩寄存器 三、汇编指令...C语言所对应的汇编代码 int main() { push ebp //将ebp压入中 mov ebp,esp //将esp...首先看main函数 使用空间是由高地址到低地址 正在调用哪个函数,espebp就维护哪个函数,在这里,我们调用的是main函数,那么就维护main函数。...通过 __tmainCRTStartup 函数调用main函数,所以要创建好__tmainCRTStartup 的帧 push ebp push ebp就是把__mainCRTStartup 函数底的地址压...指令,代表出 将edi,esi和ebx弹出 add esp,8这条指令,该指令的执行结果是让esp指针指向的地址加8 mov dword ptr [ebp-20h],eax指令。

10310
领券