参数传递:如果参数少于4个,通过a0-a3寄存器传递参数,否则其余通过堆栈传递。
参数作为调用者(caller)栈帧的一部分,4个32bits空间为a0~a3预留(即使参数通过寄存器传递)。被调者(callee)在函数前言部分分配自己的栈空间分配(返回地址/栈帧指针/局部变量),同时栈帧指针(fp)将指向最新的栈空间,并且所有局部变量通过栈帧指针偏移寻址,堆栈指针(sp)不再发生变化。
以下代码调用栈结构如下图所示:
int FunA()
{
return FunB();
}
int FunB()
{
return FunC();
}
在函数前言部分,往往有如下语句:
00400264 <fun5>:
400264: 27bdffe0 addiu sp,sp,-32 //分配栈帧
400268: afbf001c sw ra,28(sp) //保存返回地址
40026c: afbe0018 sw s8,24(sp) //保存堆帧指针
400270: 03a0f021 move s8,sp //更新栈帧指针
编译器在编译函数时,能够计算出其局部变量以及参数需要的存储空间,在函数前言部分通过偏移sp指针为这些变量分配空间。例如funB()分配的栈空间为:ra+fp+local variables+arguments。
///
int fun5(int a,int b, int c,int d,int e)
{
int abc = e;
return fun4(a,b,c,d)+ abc;
}
int main(void)
{
int ret;
int a;
int b;
int c;
int d;
a = 1;
b = 2;
c = 3;
d = 4;
ret = fun5(a,b,c,d,5);
return 0;
}
00400264 <fun5>:
400264: 27bdffe0 addiu sp,sp,-32 /*1个局部变量+4个参数+ ra +fp + 1个pad = 32*/
400268: afbf001c sw ra,28(sp)
40026c: afbe0018 sw s8,24(sp)
400270: 03a0f021 move s8,sp
400274: afc40020 sw a0,32(s8)
400278: afc50024 sw a1,36(s8)
40027c: afc60028 sw a2,40(s8)
400280: afc7002c sw a3,44(s8)
400284: 8fc20030 lw v0,48(s8)
400288: 00000000 nop
40028c: afc20010 sw v0,16(s8)
400290: 8fc40020 lw a0,32(s8)
400294: 8fc50024 lw a1,36(s8)
400298: 8fc60028 lw a2,40(s8)
40029c: 8fc7002c lw a3,44(s8)
4002a0: 0c100084 jal 400210 <fun4>
4002a4: 00000000 nop
4002a8: 8fc30010 lw v1,16(s8)
4002ac: 00000000 nop
4002b0: 00431021 addu v0,v0,v1
4002b4: 03c0e821 move sp,s8
4002b8: 8fbf001c lw ra,28(sp)
4002bc: 8fbe0018 lw s8,24(sp)
4002c0: 03e00008 jr ra /*jump reg*/
4002c4: 27bd0020 addiu sp,sp,32
004002c8 <main>:
4002c8: 27bdffc8 addiu sp,sp,-56
4002cc: afbf0034 sw ra,52(sp)
4002d0: afbe0030 sw s8,48(sp)
4002d4: 03a0f021 move s8,sp
4002d8: 24020001 li v0,1 /*没有采用优化选项,所以对每个变量的操作均会访问内存*/
4002dc: afc2001c sw v0,28(s8)
4002e0: 24020002 li v0,2
4002e4: afc20020 sw v0,32(s8)
4002e8: 24020003 li v0,3
4002ec: afc20024 sw v0,36(s8)
4002f0: 24020004 li v0,4
4002f4: afc20028 sw v0,40(s8)
4002f8: 24020005 li v0,5
4002fc: afa20010 sw v0,16(sp)
400300: 8fc4001c lw a0,28(s8)
400304: 8fc50020 lw a1,32(s8)
400308: 8fc60024 lw a2,36(s8)
40030c: 8fc70028 lw a3,40(s8)
400310: 0c100099 jal 400264 <fun5> /* jal:jump and link*/
400314: 00000000 nop
400318: afc20018 sw v0,24(s8)
40031c: 00001021 move v0,zero
400320: 03c0e821 move sp,s8
400324: 8fbf0034 lw ra,52(sp)
400328: 8fbe0030 lw s8,48(sp)
40032c: 03e00008 jr ra
400330: 27bd0038 addiu sp,sp,56