Printf 不定参
一些规定
- 不定参数的列表必须在整个函数的参数列表的最后
- 函数调用时参数传递是使用堆栈来实现的
- 在51 和arm中,不论怎么传递参数,都确保是向下生长的栈(51是模拟的一个),第一个参数在最低地址即可,否则如果是向上生长的堆栈,取参数的宏就需要做改变了
ARM传递参数
- 当少于四个时,按从左到右的顺序依次放在r0,r1,r2,r3中;
- 当多于四个时,前四个放在r0,r1,r2,r3中,剩余的放在堆栈中,最后一个参数先入栈,第五个参数最后入栈,即从右到左入栈
例子如下:,传递参数先在r0,r1,r2,r3,然后放进栈中
48: testStack("1",(int)2,(int)3,(int)4,(int)5,(int)6,(int)7,(int)8,(int)9,(int)10,(int)11,(int)12,(int)13);
0x0800028A 200D MOVS r0,#0x0D
0x0800028C 210C MOVS r1,#0x0C
0x0800028E 220B MOVS r2,#0x0B
0x08000290 230A MOVS r3,#0x0A
0x08000292 E9CD3205 STRD r3,r2,[sp,#0x14]
0x08000296 E9CD1007 STRD r1,r0,[sp,#0x1C]
0x0800029A 2009 MOVS r0,#0x09
0x0800029C 2108 MOVS r1,#0x08
0x0800029E 2207 MOVS r2,#0x07
0x080002A0 2306 MOVS r3,#0x06
0x080002A2 E9CD3201 STRD r3,r2,[sp,#0x04]
0x080002A6 E9CD1003 STRD r1,r0,[sp,#0x0C]
0x080002AA 2005 MOVS r0,#0x05
0x080002AC 2304 MOVS r3,#0x04
0x080002AE 2203 MOVS r2,#0x03
0x080002B0 2102 MOVS r1,#0x02
0x080002B2 9000 STR r0,[sp,#0x00]
0x080002B4 A014 ADR r0,{pc}+4 ; @0x08000308
0x080002B6 F7FFFFBD BL.W testStack (0x08000234)
使用时直接用堆栈,取出r0~~r3的值
10: void testStack(char * format, ...)
0x08000232 4770 BX lr
11: {
0x08000234 B40F PUSH {r0-r3}
0x08000236 B570 PUSH {r4-r6,lr}
12: char *p = (char * )&format;
13: int i;
14: int b;
15:
16:
0x08000238 AC04 ADD r4,sp,#0x10
.........................
当参数个数较少时, 可能也就单纯的赋值到r0~~r3
#include "stdio.h"
int a1(int b)
{
return (b)+1;
}
long a[10];
void SystemInit(){;}
void testStack(int format, ...)
{
char *p = (char * )&format;
int i;
int b;
a[0]=format;
a[1]=(long)&format;
p = p + sizeof(int);
b=(int)p;
a1(b);
i = *((int *)p);
a[