1.C语言函数调用的汇编代码
void main()
{
.....
.....
delay();
语句1;
语句2;
}
delay函数调用的时候,编译成的汇编代码是:
STMDB R13!,{R4-R5};R4和R5入栈,因为delay函数中用到了R4和R5
.......
LDMIA R13!,{R4-R5};退出函数的时候,在将R4和R5原来的值恢复
BX R14 ;返回原来的地方
我们发现规律就是所有函数调用代码编译成汇编的时候,首先会将要使用到的寄存器压栈,在最后即将返回main函数的时候,再将R14和R15原来的值从栈里面恢复出来。根据观察,发现所有的函数调用都是这个套路,所有大家要记住这个特点。
2.参数传递
2.1参数少于4个,包括4个
比如说下面这种情况:
void main()
{
.....
.....
delay(1,2,3,4);
语句1;
语句2;
}
传递4个参数:1,2,3,4。大家看看汇编代码是怎么样的。
MOV R3,#0x00000004
MOV R2,#0x00000003
MOV R1,#0x00000002
MOV R0,#0x00000001
大家看到这四个参数是通过R0,R1,R2,R3四个寄存器传递到delay函数中的。
2.2参数为5个,多于4个情况
比如说下面这种情况:
void main()
{
.....
.....
delay(1,2,3,4,5);
语句1;
语句2;
}
传递4个参数:1,2,3,4,5。大家看看汇编代码是怎么样的。
MOV R0,#0x00000005
MOV R3,#0x00000004
MOV R2,#0x00000003
MOV R1,#0x00000002
STR R0,[R13] ;第5个参数放到堆栈中传递
MOV R0,#0x00000001
大家看到第5个参数被压入了栈中,就是通过栈空间来传递第5个参数,我在delay函数中看到了对应的汇编指令是LDR R12,[R13,#0x0008],就是将第5个参数取出来放到R12中,供后面代码使用。所以得出的结论是,函数传递参数是通过R0到R3完成,超过4个参数就放到栈里面来传递。
3.函数中的局部变量放到哪里
比如说下面的程序:
void dely(int a, int b, int c, int d, int e)
{
int sum = a + b + c + d + e;
int t1 = 21;
int t2 = 22;
int t3 = 23;
int t4 = 24;
int t5 = 25;
int t6 = 26;
int t7 = 27;
int t8 = 28;
int t9 = 29;
int t10 = 30;
int t11 = 31;
int t12 = 32;
int t13 = 33;
int t14 = 34;
int t15 = 35;
int t16 = 36;
int t17 = 37;
int t18 = 38;
int t19 = 39;
int t20 = 40;
int t21 = 41;
int t22 = 42;
int t23 = 43;
int t24 = 44;
int t25 = 45;
int t26 = 46;
sum = t1+t2+t3+t4+t5+t6+t7+t8+t9+t10+t11+t12+t13+t14+t15+t16;
}
void main()
{
.....
.....
delay(1,2,3,4,5);
语句1;
语句2;
}
大家觉得t1,t2,t3,t4...t26都放到哪里了呢?我们看看汇编代码:
上图中是debug模式的界面,当前PC已经走到34行语句处,我们主要是观察上图中我标红框的几个地方。第一个处R0到R3的值是我传递的形参值1,2,3,4,第二处R4到R12的值是22,23,24,25,26,27,28,21,也就是我们的局部变量t1到 t8,这些局部变量的值都用R寄存器来保存。再看第三处红框处,地址从0x40000FBC到0x40000F78都在栈空间中,这里面存放的值是t9:29,t10:30,t11:31,t12:32,t13:33,t14:34,t15:35,t16:36,t17:37,t18:38,t19:39,t20:40,t21:41,t22:42,t23:43,t24:44,t25:45,t26:46,这些局部变量的值都被存放到了栈空间,主要是变量太多,寄存器不够用了,就将多余的变量开辟到了栈空间。我们最后在看看这个sum求和的汇编代码。
ADD R11,R12,R4
ADD R11,R11,R5
ADD R11,R11,R6
ADD R11,R11,R7
ADD R11,R11,R8
ADD R11,R11,R9
ADD R14,R11,R10
LDR R11,[R13,#0x0044]
ADD R14,R14,R11
LDR R11,[R13,#0x0040]
ADD R14,R14,R11
LDR R11,[R13,#0x003C]
ADD R14,R14,R11
LDR R11,[R13,#0x0038]
ADD R14,R14,R11
LDR R11,[R13,#0x0034]
ADD R14,R14,R11
LDR R11,[R13,#0x0030]
ADD R14,R14,R11
LDR R11,[R13,#0x002C]
ADD R14,R14,R11
LDR R11,[R13,#0x0028]
ADD R11,R11,R14
STR R11,[R13,#0x0048]
ADD R13,R13,#0x0000004C
LDMIA R13!,{R4-R11,R14}
BX R14
是不是觉得很清晰了。得出的结论就是函数局部变量开辟的空间要么在寄存器里,要么在栈空间里。