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

函数调用过程(帧)

开发环境 Ubuntu 14.04(32bits) GCC 编辑器 Cmd Markdown 画图工具 Processon 1,函数调用过程 今天先介绍下基本的函数调用过程,即帧。...1.1帧 每个函数调用都对应一个帧。每个帧由ESP和EBP寄存器来确定。每个函数执行时,其局部变量都是在自己对应的帧内分配内存。...假设A函数调用B函数,此时正在执行B函数,需要指出的是,当执行完当前函数B后,返回调用函数A,此时执行函数B时,为B函数的局部变量分配的的内存空间也就不存在了。...,此处将j的值压 movl 20(%esp), %eax //将变量i的值赋给eax寄存器 movl %eax, (%esp) //将变量i的值压 call test //调用test函数,...函数时,对应的帧见下图 当函数test返回后,main函数帧如下图

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

关于函数参数入的思考(函数调用约定,入顺序)

int __cdecl function(int a,int b) // 明确指出C调用约定 约定的内容有: (1)参数入顺序是从右向左; (2)在被调用函数 (Callee) 返回后...和__stdcall类似,它约定的内容有: (1) 函数的第一个和第二个DWORD参数(或者尺寸更小的)通过ecx和edx传递,其他参数通过从右向左的顺序压; (2)被调用者清理堆栈;...由于成员函数调用还有一个this指针,因此必须特殊处理,thiscall意味着: (1) 参数从右向左入; (2) 如果参数个数确定,this指针通过ecx传递给被调用者;如果参数个数不确定,...this指针在所有参数压后被压入堆栈; (3)对参数个数不定的,调用者清理堆栈,否则函数自己清理堆栈。...这些操作完成之后,分别将dword ptr [ebp-0D0h]处的值、最终的i和i入。再三次调用cout.operator<<函数将它们输出。所以程序的最终结果是11,11,10。

2.4K31

函数调用是如何变化的?

大家都知道函数调用是通过来实现的,而且知道在中存放着该函数的局部变量。但是对于的实现细节可能不一定清楚。本文将介绍一下在Linux平台下函数是如何实现的。...帧的结构 函数调用的时候都是在空间上开辟一段空间以供函数使用,所以,我们先来了解一下通用帧的结构。...在函数调用之前,调用者会为调用函数做准备。...由于rbp中的地址处总是“上一层函数调用时的rbp值”,而在每一层函数调用中,都能通过当时的%rbp值“向上(底方向)”能获取返回地址、参数值,“向下(顶方向)”能获取函数局部变量值。...通过的结构,可以知道,rbp上面就是调用函数调用调用函数的下一条指令的执行地址,所以需要赋值给rip,来找回调用函数里的指令执行地址。

3K21

VC 2015 调用查看主函数调用详情的设置

其实在进入 main 函数前,操作系统、编译器等已经做了很多工作了。只要在 VC 中,通过调用就可以看到相关一些内容。这里使用 VC 2015 来进行简单的演示。...通过CTRL + ALT + C 打开调用窗口,调用窗口如下所示。 可以看到,此时调用顶是 main 函数,也就是我们的代码当中。...通过调用可以看到,在 main 函数上面还有 “外部代码”,还有一个没有 kernel32.dll 符号的提示。这样已经可以看出,在 main 函数之前肯定是有相关的代码已经被执行了。...在调用窗口上单击右键,在弹出的菜单上选择 “显示外部代码”,在调用窗口中就会把 “外部代码” 显示出来,如下图所示。...@BaseThreadInitThunk@12() 已经被显示出来了,继续在 ntdll.dll 上进行加载,都加载完后的调用显示如下: 可以看到,调用中的调用关系的显示也都完整了。

18120

C语言函数调用帧结构

函数返回地址:保存当前函数调用前的“断点”信息,也就是函数调用前的指令位置,以便在函数返回时能够恢复到函数调用前的代码区中继续执行指令。...(1)这里首先main函数建立自己的帧结构;main()函数是由__tCRTStartup()函数调用的,所以mainCRTStratup()函数调用__tmainCRTStra()函数的时候就会从上为...函数fun的执行也许还会调用别的函数,甚至递归地调用foo本身。然而,只要EBP寄存器在这些子调用返回时被恢复,就可以继续用EBP加上偏移量的方式访问实际参数,局部变量和临时存储。...我们可以把参数一起弹出,这可以通过把指针实现:add esp, 8此时fun函数调用结束帧结构恢复至图一。...如果在函数调用前,EAX,ECX和EDX寄存器的值被保存在中,调用者main函数现在可以把它们弹出。这个动作之后,顶就回到了我们开始整个函数调用过程前的位置。这样整个函数调用就结束了

1.3K30

上理解 Go语言函数调用

[Linux_stack-1617529674577] 在现代主流机器架构上(例如x86)中,都是向下生长的。的增长方向是从高位地址到地位地址向下进行增长。...综上在函数调用中,关于参数的传递我们可以知道两个信息: 参数完全通过传递 从参数列表的右至左压 下面是调用 add 函数之前的调用调用详情: [call stack] 当我们准备好函数的入参之后...小结以下调用规则: 参数完全通过传递 从参数列表的右至左压 返回值通过传递,返回值的空间在参数之前 函数调用完毕后,调用方(caller)会负责的清理工作 结构体方法:值接收者与指针接收者...其实这段汇编和其他的函数调用的汇编是一样的,没啥好讲的,在调用 test 函数之前就是做了一些的初始化工作。...函数地址值存在 main 调用顶,然后调用完 test 函数之后会将存放在 (SP) 的 test.func1 函数地址值写入到 AX 中,然后执行调用下面的指令进行调用: 0x0031 00049

2K30

33.Linux驱动调试-根据oops的信息,确定函数调用过程

上章链接入口: https://blog.csdn.net/qq_16933601/article/details/104327937 在上章里,我们分析了oops的PC值在哪个函数出错的 本章便通过信息来分析函数调用过程...若c()函数出问题后,内核就会打印b()函数的内容(0x03,LR), 打印a()函数的内容(0x02,LR),直到sp到达顶为止   其中lr值,便代表各个函数调用关系 3.接下来我们便以上章的oops...3.1先来看first_drv_open()函数,找到STMDB入的lr值,来确定被哪个函数调用的 ?   如上图所示,first_drv_open()函数里,通过stmdb sp!...,所以c008d888位于内核的某个函数里 3.2 然后将内核进行反汇编   在内核源码的根目录下: # arm-none-linux-gnueabi-objdump -D vmlinux > vmlinux.txt...如上图所示, nameidata_to_filp函数存了6个值,所以,第二个值lr= c0089fb8 4.最终分析出,信息的调用过程如下: ret_fast_syscall()->   sys_open

89430

37.Linux驱动调试-根据oops的信息,确定函数调用过程

在上章里,我们分析了oops的PC值在哪个函数出错的 本章便通过信息来分析函数调用过程 1.上章的oops信息如下图所示: 9fe0: 代表最初的顶SP寄存器位置 9e80:代表函数出错的SP寄存器位置...LR), 打印a()函数的内容(0x02,LR),直到sp到达顶为止 其中lr值,便代表各个函数调用关系 3.接下来我们便以上章的oops里的信息来分析 在上章里,我们找到PC值bf000078在...3.1先来看first_drv_open()函数,找到STMDB入的lr值,来确定被哪个函数调用的 如上图所示,first_drv_open()函数里,通过stmdb      sp!...c008d888位于内核的某个函数里 3.2 然后将内核进行反汇编 在内核源码的根目录下: # arm-none-linux-gnueabi-objdump -D vmlinux > vmlinux.txt...(此处省略n字) 4.最终分析出,信息的调用过程如下: ret_fast_syscall()->   sys_open()->      do_sys_open()->         do_filp_open

2K50

linux shell函数定义和调用

说起函数调用,相信大家也不会陌生,然而对于初学Shell的我来说,Shell中函数调用方式却有点让我不太习惯,自己也走了不少的弯路,因为传递参数时出了一个很“自然”的错误,也让我吃了不少的苦头,所以总结一下...Shell中函数调用方法。...那大家可能就郁闷了,函数调用或多或少总是会需要一些参数,那么这些参数要怎么传递进来呢?...首先,程序会要求你输入一个数学,然后调用函数来进行输出的功能。...,因为你并不一定知道你调用函数函数外有什么变量存在也不知道它的值是什么,也不能保证别人在使用你的函数时会传递你在函数中使用到的变量名,如这里的n,别人在使用时可能传递的就是他自己定义的变量,如Count

1.9K70

Linux函数与系统调用

程序中调用了 printf() 函数,而库函数 printf 本质上是调用了系统调用 write() 函数,实现了终端信息的打印功能。 二、库函数函数可以理解为是对系统调用的一层封装。...所有 C 函数库是相同的,而各个操作系统的系统调用是不同的。 函数调用调用函数库中的一个程序,而系统调用调用系统内核的服务。...函数调用属于过程调用,开销较小,而系统调用需要切换到内核上下文环境然后切换回来,开销较大 在C函数库libc中大约 300 个程序,在 UNIX 中大约有 90 个系统调用 函数库典型的 C 函数:...五、正确理解库函数高效于系统调用 首先解释,上述说明的库函数性能远高于系统调用的前提是,库函数种没有使用系统调用。再来解释下某些包含系统调用的库函数,然而其性能确实也要高于系统调用。...当一个进程正在运行,遇到读写文件操作,会发生一个中断,中断后系统会把当前用户进程的一些寄存器信息保存在内核堆栈中,接着去处理中断服务程序,这里是要去执行系统调用Linux 中通过执行 int $0x80

7.3K30

JavaScript 调用

(anonymous)中,并且压入调用(也就是入)开始逐行执行 首先是第一行 global begin,压入调用 执行 global begin 在控制台打印完毕后,出 接下来就遇到了函数的声明...bar 和 foo ,只有代码的调用才会入,声明是不会的 遇到了 foo 函数调用,压入调用 执行 foo 函数,foo 函数第一行是 foo task 压入调用 执行 foo task (控制台打印...) 完成后,往下就是调用了 bar 函数,将 bar 函数压入调用 在 bar 函数执行过程中将 bar task 入 执行 bar task (控制台打印)完后,也代表我们的 bar 函数执行完成...,bar 函数执行完成也代表 foo 函数执行完成,将它们依次出。...最后 global end 也压入调用 最后将 global end 入,执行完毕后出。整个匿名函数(anonymous)也执行完成 在浏览器调试工具右侧可以看到调用

42900

程序Crash了却无法捕获正确的函数调用

,而这个仅有的一些线程函数调用,也并不是导致程序Crash的地方。...比较隐晦的一些场景,并不是自己编写的程序代码显示的调用退出进程API,而是由于一些API调用或者异常处理导致的: 比如微软的安全函数,strcpy_s在VS2005中比如当目标buffer空间不够就会调用...(笔者此时查看VS2015版本,默认行为已经不会调用了TerminateProcess,而是返回错误,微软也是在各位程序员采坑的情况下不断的优化自己的CRT库) 在抛出异常Unwind过程中,会调用一些局部变量的析构函数...既然明确了这个场景后,有个麻烦的事情,程序中有很多地方,包括第三方库都会调用strcpy_s等这类函数,而且异常处理的地方也有很多,很难通过代码审查找到问题所在,更有可能的是,还有其他的退出进程的调用场景没有列出来...TerminateProcess: 7790f210 8bff mov edi,edi 当程序运行到断点TerminateProcess处,查看函数调用,就可以找到程序出错的地方了

93410

详解Linux的系统调用fork()函数

Linux系统中,fork()是一个非常重要的系统调用,它的作用是创建一个新的进程。...具体来说,fork()函数会在当前进程的地址空间中复制一份子进程,并且这个子进程几乎完全与父进程相同,包括进程代码、数据、堆栈以及打开的文件描述符等。...fork()函数的语法如下: #include pid_t fork(void); 其中,参数pid_t代表进程id,而fork()函数返回值则有以下两种情况: 如果返回0,表示当前进程是子进程...此外,fork()函数还可以通过返回值来区分父进程和子进程,这使得父进程可以管理子进程的行为,例如等待子进程结束、获取子进程的状态等。...需要注意的是,fork函数会返回两次,一次是在父进程中返回子进程的进程ID,一次是在子进程中返回0。

48730

论 : 递归与式访问,如何用实现所有递归操作(函数调用底层篇)

上一篇 : 论 : 递归与式访问,如何用实现所有递归操作(基础知识篇) 2.函数调用底层篇(了解递归调用的硬件实现) 一开始,main函数没有调用add之前他的帧如下图,当然,下面只是简略介绍...当要调用add函数的时候main 将 自己的变量拷贝后压入中,我们称之为“形参” ?...上图中变量c 和变量d的拷贝就是所谓的”形参“ 接下来将main函数的ebp地址压入中保存,以便add函数调用完之后恢复main在内存中的帧 ?...而从 ebp + 8 和 ebp + 12 读取到的正好是main函数帧中的形参 ? 帧通信总结1. 子函数直接调用函数帧内的形成,访问父函数 这是子向父索求信息,那么父向子索取信息呢?...1.子函数直接调用函数帧内的形成,访问父函数 2.父函数直接访子函数在EAX中遗留的返回值 3.父函数调用函数,子函数创建帧,子函数完成后子函数帧销毁 下一篇 : 论 : 递归与式访问

84130

ARM64下的函数sp指令调用操作

一·指令 sp:用来保存底的寄存器 ldr:把数据从内存读出来,写入寄存器 str:把数据从寄存器读出来,写入内存 二·实现 我们新建一个Xcode项目,创建一个新的.s文件。...如下 1.JPG 三·通过LLDB和内存查看空间 我们需要特别关注sp,x0,x1 寄存器的变化 当我们执行函数A时:sp指向A函数空间底部 2.JPG 此时x1 x0还未被赋值都为0x00b...当我们利用LLDB继续向下指向函数跳转到B函数时,修改x0的值,查看内存变化 IMG_5933(20210129-142055).JPG 1.JPG 我们得到了 跳转后的sp指针地址 2.JPG...sp地址:0x16f1b7820 跳转到B时:16F1B7836处写的FF值 四·结论 QQ截图20210129143830.png 汇编代码解释: sub sp,sp #0x30 拉伸空间 stp...x0,x1,[sp,#0x10] ldp x1,x0,[sp,#0x10] add sp,sp,#0x30 回缩空间 返回A函数sp底指针处

2.4K20
领券