搜索
bottom↓
回复: 14

关于函数调用过程中的问题

[复制链接]

出0入0汤圆

发表于 2009-3-18 10:59:58 | 显示全部楼层 |阅读模式
各位好:碰到一个问题感觉不是很明白,请教一下

在函数调用过程中,函数中的自动变量如果少的话,可以直接用寄存器实现,用到哪个寄存器,就要在函数头Push进来,函数尾巴Pop出去,这些是不是都靠编译器来把握了。

但是如果自动变量很多的情况,BLUELUCKY版主曾经提到过
“自动变量的情况有些特殊,它的创建操作,其实只是直接把寄存器拿来用(对于优化到寄存器中的自动变量),或者对SP进行减法操作以开出栈空间后,然后使用ldr rd, [sp, #+imm]之类的指令寻址。函数返回后,寄存器就另作它用,SP也调整回去,这就体现了自动变量生命期只在函数内的原则。”

可不可以这样理解
开辟内存的时候虽然修改的是SP的指针,但实际上对该新开出来的堆栈内存的访问都是通过LDR 和STR实现的(不涉及PUSH或者Pop),之所以用到了堆栈,是因为
使用堆栈空间存放自动变量在程序结束的时候可以通过修改SP值就达到释放内存空间的目的,比较方便,所以很多编译器采用堆栈来存储自动变量。

不知道这么理解对不对?

这么说C语言提供的动态分配空间的malloc()函数是不是也就是完成两个功能 1)修改SP(开出堆栈空间)2)堆栈空间赋值的功能

动态释放空间的free()函数是不是就是完成恢复SP的功能


感谢各位指导

aaa1982

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2009-3-18 17:27:37 | 显示全部楼层
这些问题在ARM的AAPCS中有解答。简单地说,如果不使用64位类型变量的话(如double, long long),就使用R0-R3传递前4个参数,使用r0传递返回值,被调用函数不必再push和pop它们,而是由主调函数来push和pop。编译器知道自己使用了r0-r3中的哪些,因此在调用子程序前,它自己把握要保护哪些寄存器。
寄存器的资源宝贵而有限,如果参数或者局部变量太多,则多出来的的就只好放到栈区。编译器知道放了多少个,因此它可以直接对SP进行减法来腾出栈空间。自动变量生命期的结束可以如下理解(虽然不严格但无伤大雅):在函数返回时,对于有幸得到了寄存器的变量,寄存器另作它用时就已结束;对于被打入到栈中的变量,在SP调整回去(加法)后就已结束。
动态的堆内存管理使用的是完全不同的另一套机制,与栈内存管理八杆子也打不着。你可以把堆内存想像成一条很长的公路,由不同的环卫工人负责打扫不同的路段,每个环卫工人负责的路段长度不尽相同,但他们必须负责连续的一段公路(离自己家里最近的公路)。环卫工人上岗时申请负责打扫一个路段(malloc),离职时开离职证明注销(free)。一个路段只允许一个环卫工人负责。这种合同是承包制,并且法律不允许卫生管理局单方撕毁合同————除非负责人开了离职证明,不允许再把此路段分配给他人。环卫工人的人事变动是很频繁的,随着人员的流入流出,很可能出现有很多个小路段没有人负责。举个极端的例子,公路的奇数公里起始处有人打扫,偶数公里起始处无人打扫。这样,对于100公里长的公路,被分成了100个1公里长的路段,并且累计50公里无人打扫。假设现在有一环卫工人申请负责2公里长的路段,则虽然还有50公里无人负责,但是也没法分配任何一个路段给他。另一个问题时,如果某环卫工人不知何故失踪了,由于未注销,此路段只好无人打扫。
堆内存的管理跟这个差不多,它是先静态分配一个大数组(公路),然后根据某种分配算法,把大数组分割成很多小块(路段),并保证块与块之间不重叠。当某函数使用malloc分配内存时(环卫工人上岗),就从大数组中尚未被分配出去的区段切下一块满足容量要求的块,并把首地址返回。函数使用完堆内存后,就调用free归还(开离职证明)。可见,堆内存的生命期是应用程序手动控制的。如果把malloc返回的指针弄丢了,就无法在释放内存块(环卫工人失踪)。

出0入0汤圆

 楼主| 发表于 2009-3-18 20:23:59 | 显示全部楼层
每次发帖子BlueLucky都热情的帮着解答,实在太感谢了

感谢你的生动比喻,如果想把你比喻的过程再弄明白一些,看点什么好呢。

曾经看过IAR的一个配置文件,包含heap的内容,应该就是您提到的“堆”吧。当时就比较糊涂,不知道什么意思?呵呵

aaa1982

出0入0汤圆

发表于 2009-3-18 20:58:08 | 显示全部楼层
呵呵,很PF 1楼的态度,赞一个。
顺便帮1楼挑个刺:“AAPCS”应为“ATPCS”,ARM Thumb Procedure Call Standard。

出0入0汤圆

 楼主| 发表于 2009-3-18 21:22:09 | 显示全部楼层
貌似AAPCS没问题

摘自Procedure Call Standard for the ARM® Architecture
1.3Terms and Abbreviations(Page 6)

“AAPCS : Procedure Call Standard for the ARM Architecture”

出0入0汤圆

 楼主| 发表于 2009-3-18 21:49:59 | 显示全部楼层
打开IAR的disasemble窗口看了一下

翻译成了汇编以后,0项00000000放的是一个库函数的地址,运行完了一些库函数以后,调到main(),开始执行,但不知道为什么main()函数的开始有一条Push{R4,LR}
怎么想也没弄清为什么要这么一条,哪位帮着解释一下呢。

aaa1982

(原文件名:2.jpg)

出0入0汤圆

发表于 2009-3-18 22:39:35 | 显示全部楼层
谢谢鼓励!
在main()返回后,C运行时环境还要做一些善后工作,因此需要知道返回到哪里,故而保护LR。保护R4,可能也是出于类似的原因,把R4存储某个参数。

出0入0汤圆

发表于 2009-3-18 23:18:27 | 显示全部楼层
heap就是堆。如果需要进一步理解,可以参考C语言的教程,如<<C和指针>>,也可以参考开发工具对malloc / free 函数的说明

出0入0汤圆

 楼主| 发表于 2009-3-19 08:53:28 | 显示全部楼层
感谢bluelucky的指教

还是有点不明白,为什么main()会返回呢?

main()中调用的函数可以返回(到main),所以可能需要在函数开始的地方push {需要保存的寄存器,LR},(如果函数里面还有函数

调用就需要PUSH LR,否则就不需要了)。

main函数中调用的函数可以返回到main(),但是main()如果返回的话会返回到哪里呢?

从Disasemble窗口可以看出,main函数其实也是一个库函数调用的,从这点也可以理解在main函数的开始push{R4,LR}的意思(肯定是调

用它的库函数用到了R4,并且main函数里面肯定有一大堆的函数调用,所以需要保存一下R4和LR)。

但是什么什么时候Main()会返回(到调用它的函数)呢?到现在为止,我所有的main 函数都会有一个类似while(1)的无限循环,不

会返回呀。需要main返回的情况都有哪些呢?

感谢版主和各位指教?

aaa1982

出0入0汤圆

发表于 2009-3-19 09:38:10 | 显示全部楼层
main()返回的情况比较罕见,通常用于系统软件比较另类的设计思路中。有可能C运行时库会根据main()返回后的值做一些其它的操作。另外,作为运行时库的设计者,他也必须考虑main()返回的情况。

出0入0汤圆

发表于 2009-3-19 13:31:01 | 显示全部楼层
在多任务的情况下,main()函数返回是很正常的,返回到操作系统。

出0入0汤圆

发表于 2009-3-19 14:42:45 | 显示全部楼层
操作系统常常不使用C运行时库,既有不想用也有不能用的原因。因此,操作系统要接管复位后,以及程序退出后执行的操作,完全自己定义用户程序的起止方式。最有代表性的就是,操作系统自己负责main(也可能使用其它的名字),而应用程序入口点则变成XXmain()。比如,某操作系统简称为pp,则它就可能让应用程序以ppmain()作为入口点。ppmain()通常在创建好任务与同步原语后返回。返回后操作系统就开工了。
对于楼主的例子,没有使用操作系统,因此是走C运行时库设置的框架流程的。

出0入0汤圆

发表于 2009-3-19 15:06:00 | 显示全部楼层
呵呵,楼上高手,佩服~!

出0入0汤圆

 楼主| 发表于 2009-3-19 22:10:38 | 显示全部楼层
实在感谢,看来路还很长,呵呵

学习了。

出0入0汤圆

发表于 2009-12-18 14:27:22 | 显示全部楼层
1楼说的很好,学习了。
另外我想问一下,如果考虑64位类型变量的话(如double, long long)的话,又是一个怎样的过程?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-17 19:45

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表