ARM参数传递规则
1. r0,r1,r2,r3,在调用函数时,用来存放前4个函数参数和返回值,r4-r11,r14,在调用函数时必须保存这些寄存器到堆栈当中。如果函数的参数多于4个,则多余参数存放在堆栈当中,即sp,sp+4,sp+8,…依次类推。
2. 函数内部通用的入栈出栈代码可以为:
STMFD sp!,{r4-r11,lr}
// body of ASM code
LDMFD sp!,{r4-r11,pc}
如果函数并没有用到那么多的寄存器,则没有必要把所有的寄存器入栈。如果函数要调用子函数,则r0,r1,r2,r3,r12,r14这些寄存器里面值将被改变,必须小心处理这些寄存器,一种可行的方法是,修改被调用子函数的入栈出栈代码为:
STMFD sp!,{r0-r12,lr}
// body of ASM code
LDMFD sp!,{r0-r12,pc}
3. 如果函数内部变量太多,这时候要考虑使用堆栈,这是入栈出栈代码可以为:
STMFD sp!,{r4-r11,lr}
SUB sp, sp, #stacksize
// body of ASM code
ADD sp, sp, #stacksize
LDMFD sp!,{r4-r11,pc}
4. 如果函数的参数多于4个,则函数内部的参数在堆栈中的位置依入栈出栈代码而定:
STMFD sp!,{r4-r11,lr}
LDR r4,[sp,#36] //第5个参数在堆栈中的位置
LDR r5,[sp,#40] //第6个参数在堆栈中的位置
// ……
// body of ASM code
LDMFD sp!,{r4-r11,pc}
5. 如果第5个参数是要传递地址,函数调用完以后要使用之前传进去的第5个参数,则要预留更多的堆栈空间。可参考下面代码:
//other C code
butterfly32a_16(x2m[0], x2m[1], *ptr1--, tmpSineTable8m, &rx, &ix);
//other C code
这个C函数总共有6个参数,在调用之前要预留4个堆栈单元。代码如下:
sp_0 EQU 0
sp_1 EQU sp_0 + 4
var_rx EQU sp_1 + 4
var_ix EQU var_rx+4
stacksize EQU var_ix+4
STMFD sp!,{r4-r11,lr}
SUB sp, sp, #stacksize
// other ASM code
ADD r4, sp, #var_rx
ADD r5, sp,# var_ix
STR r4, [sp,#sp_0]
STR r5, [sp,#sp_1]
// assume the r0,r1,r2,r3 are prepared well
BL butterfly32a_16
LDR r4, [sp, #var_rx] //r4 is the value of rx
LDR r5, [sp, #var_ix] //r5 is the value of ix
// other ASM code
ADD sp, sp, #stacksize
LDMFD sp!,{r4-r11,pc}