c语言中要引入子函数的代码,C与汇编:调用子函数

本文深入剖析了C语言中函数调用在汇编层面的实现过程,详细解释了rbp和rsp寄存器的作用,以及函数调用时栈帧的建立和清理。通过分析main函数和add函数的汇编代码,展示了参数传递、局部变量存储和返回值处理的细节,揭示了x64架构下栈操作的原理。
摘要由CSDN通过智能技术生成

研究目的:了解汇编如何实现C语言中的函数调用

编译器:TDM-GCC 4.9.2 64-bit Release

反汇编:Dev-C++ 5.11

C语言代码:

6433df56aa1b47f2b4d7d9a40151584c.png

该函数调用了一个简单的add函数,add函数将输入的两个参数值相加,并返回两参数之和。

main函数:

a233a88264624073952ef453ea69a644.jpg

1、2行:rbp的作用是标记基址,在一个函数的执行过程中是固定不变的,因此可借助基址与偏移量来访问栈内数据。rsp的作用是标识当前栈所占空间。main函数实际上也是被调用的一方,即在第一行代码执行前,当前rsp与rbp之间的数据为调用方数据,需要进行保护。保护方式为将调用函数的rbp保存进栈,以备时候恢复现场。然后让rbp指向rsp,以便准备使用新的栈空间。我们课本上提到x86中使用32bit的esp(extended stack pointer)和ebp(extended base pointer)作为栈指针寄存器与基址指针寄存器。然而我们的编译器是x64的,因此使用的是64bit的rbp与rsp。

3行:rsp下移0x30,这相当于开辟了一片空间以便存储临时变量

4、5行:对rbp以上的地址进行操作,那部分是调用函数的变量区,将ecx、rdx保存到那里

6行:不知用途

7、8行:对变量进行初始化,一个int变量为4个字节,即DOUBLE WORD。

9、10行:两变量由内存移入寄存器edx,eax

11行:eax存入ecx。至此两变量已分别存到了ecx与edx。借助寄存器我们可以实现函数间参数的传递。

12行:调用add函数

13行:返回值被存在eax中,因此需要把它取回赋给区域[rbp-0xc],即变量c

14行:eax用来存储返回值,因此该行对应return 0语句

15行:将rsp移回到rbp处,以此释放内存。这意味着堆栈空间的释放不代表数据被清除。只有数据被覆盖才是真正的消失

16行:将rbp恢复到调用函数前的位置

17行:结束程序,返回操作系统

add函数:

bdcab6e2e8a74b20a9c254eef5d69095.jpg

1、2、3行:类似main中的操作,开辟自己的堆栈空间。

4、5行:ecx、edx寄存器中存储了调用函数传递的参数,把它移到堆栈区以便进行各类运算。由于是调用函数的变量,把它存在rbp上方空余的空间中。

6、7行:重新把变量从堆栈区取到寄存器。虽然这样取来取去的过程显得很傻,但当这个函数变得复杂时,这样的操作是相当有必要的。在寄存器中运算使得运算速度加快,并且大量运算时不需要来回地取数据。

8行:计算a+b

9行:把计算结果存到局部堆栈区中

10行:将返回值写到eax

11、12、13行:类似main中那样,清空堆栈区后返回。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值