ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

函数

2022-02-08 23:02:14  阅读:166  来源: 互联网

标签:调用 函数 函数调用 64 寄存器 返回值


一、传参

C语言有两种传递参数的方法,分别是值传参指针传参,但其实本质都是值传参,只不过指针传参传递的值是指针罢了。

编译器会在函数调用时,对传入的参数进行复制,所以函数使用的参数和传递的参数不是同一个实体。

指针传参虽然指针本身无法被修改,但是可以修改指针指向的值,所以如果想要修改一个值,可以传递这个值的地址。

二、函数的调用约定

虽然 C 语言对于函数的调用没有规定,但对于编译器而言,每一个函数在被调用时,应该以怎样的方式通过机器指令来实现其调用过程,却存在着相应的事实标准。

调用约定规定了函数调用时需要关注的一系列问题,包括:如何将实惨传递给被调用函数,如何将返回值从被调用函数中返回,如何管理寄存器,如何管理栈内存等等。

 

在 Unix 和类 Unix 系统上,使用名为 System V AMD64 ABI(后简称 “SysV”)的调用约定。

1.函数传递

SysV约定规定,在调用函数时,对于整型和指针类型的实参,需要分别使用 rdi、rsi、rdx、rcx、r8、r9,按函数定义时参数从左到右传值,如下图所示:

 

 

 如果一个函数的传递参数超过了六个,多出来的参数按照从右往左的顺序被逐个压入栈中,如下图所示:

2.返回值传递

SysV约定规定,函数返回值为整数,且小于等于 64 位时,通过寄存器 rax 传递,当返回值大于 64 位小于 128 位时,用 rax 存储低 64 位, rdx 存储高64位,由于不知道如何表示超过 64 位的整型,所以只能看到小于 64 位的返回值用 rax 存储:

 

 

 至于浮点数,返回值用 xmm0 寄存器存储:

3.寄存器使用

SysV 调用约定对寄存器的使用也作出了规定:对于寄存器 rbx、rbp、rsp,以及 r12 到 r15,若被调用函数需要使用它们,则需要该函数在使用之前将这些寄存器中的值进行暂存,并在函数退出之前恢复它们的值(callee-saved)。而对于其他寄存器,则根据调用方的需要,自行保存和恢复它们的值(caller-saved)

4.堆栈清理

函数在结束调用前,通过 leave 指令清理自身堆栈。清理的本质是恢复函数刚进入时 rsp 和 rbp 寄存器的值。

也可以通过以下方法进行清理:

mov rsp, rbp

pop rbp

5.其他约定

1.函数在被 call 指令调用前,需要保证栈顶于 16 字节对齐。

2.从栈顶向上保留 128 字节的 “Read Zone”

Read Zone:位于栈顶向上(低地址方向)的一段固定长度的内存段,这块区域通常可以被函数调用栈中的“叶子”函数(即不再调用其他函数的函数)使用。这样,在需要额外的栈内存时,就能在一定条件下省去先调整栈内存大小的过程。

3.不同于用户函数的调用过程,系统调用(System Call)函数需使用寄存器 rdi、rsi、rdx、r10、r8、r9 传递参数。

二、栈帧

函数调用过程伴随着栈内存中数据的不断变化,每一个函数在调用时,都会在栈内存中呈现出类似的数据结构。而通过这种方式划分出来的,对应于每一次函数调用的栈内存数据块,我们一般称它为“栈帧”。栈帧中存放有与每个函数调用相关的返回地址、实参、局部变量、返回值,以及暂存数据的寄存器值等信息。

rsp 寄存器决定栈顶的位置,也决定了进程能够使用的栈的大小。

每一个函数被调用过程中产生的栈帧都会按照顺序存放在栈内存中,当函数嵌套的层级足够深时,会产生“栈溢出”错误。尾递归优化可以解决该问题。

三、尾递调用归优化

递归函数是一种在满足条件的前提下可以自己调用自己的函数,尾递归调用优化是指在一定下,编译器会直接使用跳转指令代替函数调用指令。但前提是,递归调用语句必须作为函数返回前的最后一条语句

 

 尾递归优化在函数体较小,递归调用次数很多的情况下比较明显,此时函数执行时间先对于栈帧的创建和销毁时间要小很多。

 

标签:调用,函数,函数调用,64,寄存器,返回值
来源: https://www.cnblogs.com/shuijiaoa/p/15872635.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有