ARM中断控制器

为什么在调用c函数时需要先设置栈指针?

一.栈的整体作用

 (1)保存现场/上下文  

 (2)传递参数:汇编代码调用c函数时,需传递参数  

 (3)保存临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量。

 

二.为什么汇编代码调用c函数需要设置栈 

之前看了很多关于uboot的分析,其中就有说要为C语言的运行,准备好栈。而自己在Ubootstart.S汇编代码中,关于系统初始化,也看到有栈指针初始化这个动作。但是,从来只是看到有人说系统初始化要初始化栈,即正确给栈指针sp赋值,但是却从来没有看到有人解释,为何要初始化栈。所以,接下来的内容,就是经过一定的探究,试图来解释一下,为何要初始化栈。  要明白这个问题,首先要了解栈的作用。关于栈的作用,要详细讲解的话,要很长的篇幅,所以此处只是做简略介绍。总的来说,栈的作用就是:保存现场/上下文,传递参数,保存临时变量   

1.保存现场/上下文  现场/上下文,意思就相当于案发现场,总有一些现场的情况,要记录下来的,否则被别人破坏掉之后,你就无法恢复现场了。而此处说的现场,就是指CPU运行的时候,用到了一些寄存器,比如r0,r1等等,对于这些寄存器的值,如果你不保存而直接跳转到子函数中去执行,那么很可能就被其破坏了,因为其函数执行也要用到这些寄存器。因此,在函数调用之前,应该将这些寄存器等现场,暂时保持起来(入栈push),等调用函数执行完毕返回后(出栈pop),再恢复现场。这样CPU就可以正确的继续执行了。  保存寄存器的值,一般用的是push指令,将对应的某些寄存器的值,一个个放到栈中,把对应的值压入到栈里面,即所谓的压栈。然后待被调用的子函数执行完毕的时候,再调用pop,把栈中的一个个的值,赋值给对应的那些你刚开始压栈时用到的寄存器,把对应的值从栈中弹出去,即所谓的出栈。  其中保存的寄存器中,也包括lr的值(因为用bl指令进行跳转的话,那么之前的pc的值是存在lr中的),然后在子程序执行完毕的时候,再把栈中的lr的值pop出来,赋值给pc,这样就实现了子函数的正确的返回。  

2. 传递参数  C语言进行函数调用的时候,常常会传递给被调用的函数一些参数,对于这些C语言级别的参数,被编译器翻译成汇编语言的时候,就要找个地方存放一下,并且让被调用的函数能够访问,否则就没发实现传递参数了。对于找个地方放一下,分两种情况。一种情况是,本身传递的参数不多于4个,就可以通过寄存器传送参数。因为在前面的保存现场的动作中,已经保存好了对应的寄存器的值,那么此时,这些寄存器就是空闲的,可以供我们使用的了,那就可以放参数。另一种情况是,参数多于4个时,寄存器不够用,就得用栈了。   

3..临时变量保存在栈中   包括函数的非静态局部变量以及编译器自动生成的其他临时变量 


msr 与cpsr_c

ARM每种工作模式除R0~R15共16个寄存器外,还有第17个寄存器CPSR,叫做 当前程序状态寄存器,CPSR中一些位被用于标识各种状态,一些位被用于标识当前出于什么工作模式。

其中cpsr_c代表的是这32位中的低8位,也就是控制位

msr cpsr_c 0xd2                                       //msr是arm汇编中专门用来修改cpsr这样有特定功能的寄存器的指令

                                                                  //具体请参考Arm汇编手册和Arm体系架构手册

这样的语句时,就是在更改这8位的状态


涉及到的汇编指令

参考: stdmfd,ldmfd,ldmia,ldmib的学习程序

http://blog.chinaunix.net/uid-20321537-id-1966732.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值