PowerPC栈帧理解

因为实验室项目的原因,才开始接触PowerPC,错误的地方还望看到的各位指正。


上面就是IBM的手册上面画的栈帧,他的文字描述也符合这个示意图,理解起来就是栈顶存放的是上一个栈的栈顶的地址。r1寄存器(一般作为默认的堆栈指针)存放自身的栈顶。因为没有push和pop指令,所以是通过stwu和lwzu来进行push和pop的。下面假设调用函数为main(),被调用函数为func()。根据手册上来说:


从栈底到栈顶依次存放的是

  (1)函数参数域FPR(Function Parameter Register):这个区域的大小是变化的,当调用者传递给被调用者的参数少于8个时,用GPR3-GPR10这8个寄存器就行,被调用者的栈帧中就可不要这个区域;但如果传递的参数多于8个时就需要这个区域。
 (2)通用寄存器GPR(General Parameter Register):当需要保存GPR寄存器中的一个寄存器GPRx时,就需要把从GPRx-GPR31的值都保存到堆栈帧中。
 (3)CR寄存器:即使修改了CR寄存器的某一个段CRx(x=0至7),都要保存这个CR寄存器的内容。
 (4)局部变量域(Local Variables Area):同上FPR所示,如果临时寄存器的数量不足以提供给被调用者的临时变量使用时,就会使用这个区域。
 (5)Function Parameters:跟第一个FPR重复了?暂时不知。
 (6)Padding:是补齐字节数,让当前栈帧的长度保持8Bytes的倍数。
 (7)LR链接寄存器(Link Register):也就是被调用函数的返回地址,main函数中调用func函数的那条指令的下一条指令的地址
  (8)Back Chain Word:即上一个栈帧的低地址,也是r1存放的地址值,可以把这个作为基址进行自己栈帧内的寻址
    调用的过程举例如下:

      func中开始几行汇编会为自己建立栈帧:

    func的结尾几行,会移除前面建立的栈帧,并使得SP(即GPR1)寄存器指向上一个栈帧的栈顶(即栈帧的最低地址处,也就是back chair)
    如下所示:
         



用图例来讲就是:




不过有个很奇怪的地方,按照IBM的示例代码,如果是先stwu %r1,-88(%r1);再stw %r0,+92(%r1),也就是保存在栈上的位置加的比栈分配的空间大(分配了88字节,存放的位置是+92),那保存的LR不是变成了在上一个栈帧的内部了么?这个不就跟IBM的栈帧的示意图冲突了么(栈帧示意图中的LR存在的是被调用函数自己的栈内,文字描述也是这个意思)?按代码保存的LR应该是保存在main函数还未调用func时r1+4的位置,示例如下,为了区别,调用func时的r1写成r’:

         


我去找了人家的反汇编程序看了看:

#include <stdio.h>

void fun()

{

}

int main()

{

       fun();

       return 0;

}


可以看到,在main函数的跳转的时候用的bl,bl跳转的时候可以存放LR,因为func什么也没有,所以编译器自动把保存LR到栈的部分忽略了,可能是编译器优化的结果?在上图中,func存放调用函数栈顶的方法是用的r31这个寄存器,但是在之前先保存了原先r31的值,而且是在自己的栈内。在main函数里面我们可以看到IBM手册里面说的那种建立栈帧的标准方法,但是存LR还是超过了分配给自己的栈大小(分配了16,存的位置是20(r1))。这个我也不知道是为什么存LR要保存到上一个栈,这跟栈帧示意图里面LR保存的位置不同,只能以后看能不能问到更多的牛人的意见了……

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值