Mips 栈的一些特性

原文: http://blog.csdn.net/swwcyb/article/details/8164805  

参数传递:如果参数少于4个,通过a0-a3寄存器传递参数,否则其余通过堆栈传递。

    参数作为调用者(caller)栈帧的一部分,4个32bits空间为a0~a3预留(即使参数通过寄存器传递)。被调者(callee)在函数前言部分 分配自己的栈空间分配(返回地址/栈帧指针/局部变量),同时栈帧指针(fp)将指向最新的栈空间,并且所有局部变量通过栈帧指针偏移寻址,堆栈指针 (sp)不再发生变化。

 

以下代码调用栈结构如下图所示:

  1. int FunA()  
  2. {  
  3.     return FunB();  
  4. }  
  5. int FunB()  
  6. {  
  7.     return FunC();  
  8. }  


     

 

在函数前言部分,往往有如下语句:

  1. 00400264 <fun5>:  
  2.  400264:      27bdffe0        addiu sp,sp,-32   //分配栈帧  
  3.  400268:      afbf001c        sw    ra,28(sp)   //保存返回地址  
  4.  40026c:      afbe0018        sw    s8,24(sp)   //保存堆帧指针  
  5.  400270:      03a0f021        move  s8,sp       //更新栈帧指针     


    编译器在编译函数时,能够计算出其局部变量以及参数需要的存储空间,在函数前言部分通过偏移sp指针为这些变量分配空间。例如funB()分配的栈空间为:ra+fp+local variables+arguments。

 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  1. int fun5(int a,int b, int c,int d,int e)  
  2. {  
  3.     int abc = e;  
  4.     return fun4(a,b,c,d)+ abc;    
  5. }  
  6. int main(void)  
  7. {  
  8.     int ret;  
  9.     int a;  
  10.     int b;  
  11.     int c;  
  12.     int d;  
  13.     a = 1;  
  14.     b = 2;  
  15.     c = 3;  
  16.     d = 4;  
  17.     ret = fun5(a,b,c,d,5);  
  18.     return 0;     
  19. }  


 

其反汇编代码(无优化选项)

 

  1. 00400264 <fun5>:  
  2.   400264:   27bdffe0    addiu   sp,sp,-32     /*1个局部变量+4个参数+ ra +fp + 1个pad = 32*/  
  3.   400268:   afbf001c    sw  ra,28(sp)  
  4.   40026c:   afbe0018    sw  s8,24(sp)  
  5.   400270:   03a0f021    move    s8,sp  
  6.   400274:   afc40020    sw  a0,32(s8)  
  7.   400278:   afc50024    sw  a1,36(s8)  
  8.   40027c:   afc60028    sw  a2,40(s8)  
  9.   400280:   afc7002c    sw  a3,44(s8)  
  10.   400284:   8fc20030    lw  v0,48(s8)  
  11.   400288:   00000000    nop  
  12.   40028c:   afc20010    sw  v0,16(s8)  
  13.   400290:   8fc40020    lw  a0,32(s8)  
  14.   400294:   8fc50024    lw  a1,36(s8)  
  15.   400298:   8fc60028    lw  a2,40(s8)  
  16.   40029c:   8fc7002c    lw  a3,44(s8)  
  17.   4002a0:   0c100084    jal 400210 <fun4>  
  18.   4002a4:   00000000    nop  
  19.   4002a8:   8fc30010    lw  v1,16(s8)  
  20.   4002ac:   00000000    nop  
  21.   4002b0:   00431021    addu    v0,v0,v1  
  22.   4002b4:   03c0e821    move    sp,s8  
  23.   4002b8:   8fbf001c    lw  ra,28(sp)  
  24.   4002bc:   8fbe0018    lw  s8,24(sp)  
  25.   4002c0:   03e00008    jr  ra                   /*jump reg*/  
  26.   4002c4:   27bd0020    addiu   sp,sp,32  
  27.   
  28. 004002c8 <main>:  
  29.   4002c8:   27bdffc8    addiu   sp,sp,-56  
  30.   4002cc:   afbf0034    sw  ra,52(sp)  
  31.   4002d0:   afbe0030    sw  s8,48(sp)  
  32.   4002d4:   03a0f021    move    s8,sp  
  33.   4002d8:   24020001    li  v0,1       /*没有采用优化选项,所以对每个变量的操作均会访问内存*/  
  34.   4002dc:   afc2001c    sw  v0,28(s8)  
  35.   4002e0:   24020002    li  v0,2  
  36.   4002e4:   afc20020    sw  v0,32(s8)  
  37.   4002e8:   24020003    li  v0,3  
  38.   4002ec:   afc20024    sw  v0,36(s8)  
  39.   4002f0:   24020004    li  v0,4  
  40.   4002f4:   afc20028    sw  v0,40(s8)  
  41.   4002f8:   24020005    li  v0,5  
  42.   4002fc:   afa20010    sw  v0,16(sp)  
  43.   400300:   8fc4001c    lw  a0,28(s8)  
  44.   400304:   8fc50020    lw  a1,32(s8)  
  45.   400308:   8fc60024    lw  a2,36(s8)  
  46.   40030c:   8fc70028    lw  a3,40(s8)  
  47.   400310:   0c100099    jal 400264 <fun5>       /* jal:jump and link*/  
  48.   400314:   00000000    nop  
  49.   400318:   afc20018    sw  v0,24(s8)  
  50.   40031c:   00001021    move    v0,zero  
  51.   400320:   03c0e821    move    sp,s8  
  52.   400324:   8fbf0034    lw  ra,52(sp)  
  53.   400328:   8fbe0030    lw  s8,48(sp)  
  54.   40032c:   03e00008    jr  ra  
  55.   400330:   27bd0038    addiu   sp,sp,56


    还有一篇文章介绍mips栈使用
    特性: http://www.newsmth.net/nForum/#!article/Programming/2823
    发信人: newmirror (yestoday once more), 信区: Programming        
    标  题: 总结了一下mips的栈使用惯例,也许有人感兴趣.
    发信站: BBS 水木清华站 (Fri Jun 14 12:14:01 2002)
      
    stack usage convention(栈使用惯例?)
    1.stack 在内存中朝低地址的方向增长.
    2.栈指针寄存器 sp ($29)指向栈的最低的word address(栈顶)
    3.栈内的内容通过从sp的正的word offset来引用.
    4.一个函数需要的所有的栈空间(活动记录)必须在函数开始的时候一次全部分配,还必须
    双字对齐.
    5.栈空间的分配是通过减去栈指针(加上一些需要保持对齐的)
    6.当从过程返回的时候,sp加上它在过程被调用的时候减去的值,活动记录被回收.
    7.没有子函数的函数至少需要24个字节的空间:为a0-a3(输入参数)保留4个字的,返回地
    址一个字和一个
    字用来双字对齐.保存a0-a3这样使得调用函数可以在被调用的函数中保留输入的参数.这
    个规则一开始
    引入是为了处理参数个数可变的函数,但是现在不管什么情况都保存a0-a3.
    8.一个函数的活动记录按照地址升序;依次存放:
         8.1:a0-a3
         8.2:传递给被调用函数的参数(outgoing arguments)
         8.3:从双字对齐的位置开始保存浮点寄存器.(从号最小的寄存器开始)
         8.4:保存寄存器.(从号最小的开始)(其中包括返回地址寄存器ra)
         8.5:函数分配给局部变量的空间(local)
    9. .frame指令通常和三个参数相联系.
         9.1:sp
         9.2:存放fp的位置.
         9.3:返回地址.
    btw:
    1)outgoing arguments:
    Outgoing arguments are only meaningful for nonleaf routine
    The Outgoing Arguments area must be large enough to hold all the arguments p
    assed when calling another function, including all arguments passed in regis
    ters.
    2)a0-a3:incoming args
    ---------------------------------------------
    过程格式:
    一个过程主要包括三个部分:prologue,body,epilogue
    prologue:
             1.规定函数入口点.
             2.分配栈空间.
             3.保存需要的寄存器.
    epilogue:
             1.恢复寄存器.
             2.回收空间.
             3.把控制权返回给caller.
              
      
     

 

posted @ 2013-03-12 21:08  三年之鱼  阅读(1880)  评论(1编辑  收藏  举报