汇编调用C函数之前要设置好栈??
2015-10-15 14:49
274 查看
由于ARM在各种执行模式下都需要设置各自的栈指针,所以"ldr sp,=xxxx"操作较多。根据ARM的ATPCS规则,对栈的操作属于FD(满递减),即栈指针一直指向栈顶元素,是按地址减小的方向增长的,所以一般将SP设置在地址的最高处。
在on_sdram中:
ldr sp, =4096 @ 设置中断模式栈指针
ldr sp, =0x34000000 @ 设置系统模式栈指针,
这是分别设定中断模式和系统模式下的堆栈指针到4096(SRAM的有效地址的最高地址)和0x34000000(从0x30000000开始的64M的SDRAM的最高地址处,此时SDRAM已经初始化,可以使用了)。
C语言还是要转换成汇编指令的,处理比较复杂时,就要利用到栈来保存中间结果之类的,这时候,在你进入C语言程序之前,就要设置好栈了。函数调用是通过栈来实现的。。。调用完函数返回时,需要通过栈里的地址来返回。
同时,函数的参数也是通过栈来传递。
总的来说,栈的作用就是:保存现场/上下文,传递参数,保存临时变量
1.保存现场/上下文
现场/上下文,意思就相当于案发现场,总有一些现场的情况,要记录下来的,否则被别人破坏掉之后,你就无法恢复现场了。而此处说的现场,就是指CPU运行的时候,用到了一些寄存器,比如r0,r1等等,对于这些寄存器的值,如果你不保存而直接跳转到子函数中去执行,那么很可能就被其破坏了,因为其函数执行也要用到这些寄存器。因此,在函数调用之前,应该将这些寄存器等现场,暂时保持起来(入栈push),等调用函数执行完毕返回后(出栈pop),再恢复现场。这样CPU就可以正确的继续执行了。
保存寄存器的值,一般用的是push指令,将对应的某些寄存器的值,一个个放到栈中,把对应的值压入到栈里面,即所谓的压栈。然后待被调用的子函数执行完毕的时候,再调用pop,把栈中的一个个的值,赋值给对应的那些你刚开始压栈时用到的寄存器,把对应的值从栈中弹出去,即所谓的出栈。
其中保存的寄存器中,也包括lr的值(因为用bl指令进行跳转的话,那么之前的pc的值是存在lr中的),然后在子程序执行完毕的时候,再把栈中的lr的值pop出来,赋值给pc,这样就实现了子函数的正确的返回。
2.传递参数
C语言进行函数调用的时候,常常会传递给被调用的函数一些参数,对于这些C语言级别的参数,被编译器翻译成汇编语言的时候,就要找个地方存放一下,并且让被调用的函数能够访问,否则就没发实现传递参数了。对于找个地方放一下,分两种情况。一种情况是,本身传递的参数不多于4个,就可以通过寄存器传送参数。因为在前面的保存现场的动作中,已经保存好了对应的寄存器的值,那么此时,这些寄存器就是空闲的,可以供我们使用的了,那就可以放参数。另一种情况是,参数多于4个时,寄存器不够用,就得用栈了。
3.临时变量保存在栈中
包括函数的非静态局部变量以及编译器自动生成的其他临时变量。
在on_sdram中:
ldr sp, =4096 @ 设置中断模式栈指针
ldr sp, =0x34000000 @ 设置系统模式栈指针,
这是分别设定中断模式和系统模式下的堆栈指针到4096(SRAM的有效地址的最高地址)和0x34000000(从0x30000000开始的64M的SDRAM的最高地址处,此时SDRAM已经初始化,可以使用了)。
C语言还是要转换成汇编指令的,处理比较复杂时,就要利用到栈来保存中间结果之类的,这时候,在你进入C语言程序之前,就要设置好栈了。函数调用是通过栈来实现的。。。调用完函数返回时,需要通过栈里的地址来返回。
同时,函数的参数也是通过栈来传递。
总的来说,栈的作用就是:保存现场/上下文,传递参数,保存临时变量
1.保存现场/上下文
现场/上下文,意思就相当于案发现场,总有一些现场的情况,要记录下来的,否则被别人破坏掉之后,你就无法恢复现场了。而此处说的现场,就是指CPU运行的时候,用到了一些寄存器,比如r0,r1等等,对于这些寄存器的值,如果你不保存而直接跳转到子函数中去执行,那么很可能就被其破坏了,因为其函数执行也要用到这些寄存器。因此,在函数调用之前,应该将这些寄存器等现场,暂时保持起来(入栈push),等调用函数执行完毕返回后(出栈pop),再恢复现场。这样CPU就可以正确的继续执行了。
保存寄存器的值,一般用的是push指令,将对应的某些寄存器的值,一个个放到栈中,把对应的值压入到栈里面,即所谓的压栈。然后待被调用的子函数执行完毕的时候,再调用pop,把栈中的一个个的值,赋值给对应的那些你刚开始压栈时用到的寄存器,把对应的值从栈中弹出去,即所谓的出栈。
其中保存的寄存器中,也包括lr的值(因为用bl指令进行跳转的话,那么之前的pc的值是存在lr中的),然后在子程序执行完毕的时候,再把栈中的lr的值pop出来,赋值给pc,这样就实现了子函数的正确的返回。
2.传递参数
C语言进行函数调用的时候,常常会传递给被调用的函数一些参数,对于这些C语言级别的参数,被编译器翻译成汇编语言的时候,就要找个地方存放一下,并且让被调用的函数能够访问,否则就没发实现传递参数了。对于找个地方放一下,分两种情况。一种情况是,本身传递的参数不多于4个,就可以通过寄存器传送参数。因为在前面的保存现场的动作中,已经保存好了对应的寄存器的值,那么此时,这些寄存器就是空闲的,可以供我们使用的了,那就可以放参数。另一种情况是,参数多于4个时,寄存器不够用,就得用栈了。
3.临时变量保存在栈中
包括函数的非静态局部变量以及编译器自动生成的其他临时变量。
相关文章推荐
- C++ 基础题目
- RMAN备份与恢复之不完全恢复
- 使用Express搭建服务器
- UG NX 二次开发 转档图片
- 信息安全系统设计基础第6周学习总结
- Android 查看keystore SHA1并使用自定义keystore
- 如何在play框架的前端_通过Angularjs框架使用html模板
- 《平凡的世界》有感
- 浏览器判断及IE版本区分
- 138_多线程(多线程-同步函数的锁是this)
- 非阻塞Connect对于select时应注意问题
- android studio 导入 github 项目代码
- Android下怎么利用webView去调用JS里面的方法
- 解决tableViewCell分割线不到左边界的问题
- Linux 基础知识: GPT分区基础知识及如何在GPT分区上安装WIN7
- Google 的GSON使用详解
- 在Eclipse中搭建jBPM6.2运行环境及插件方法
- python爬虫小项目之计算研究生成绩绩点
- android:layout_weight的真实含义
- linux 下 postgres 的使用总结