在学习ARM过程中,想要了解函数调用时参数传递是如何用堆栈来实现的,就需要写一段代码将每个参数的地址打印出来,查看堆栈的存储内容;以重写printf为例,首先查看x_86平台下的各数据类型所占的字节数,
sizeof int = 4
sizeof char = 1
sizeof float = 4
sizeof double = 8
sizeof char * = 4
sizeof int * = 4
sizeof flaot* = 4
sizeof double* =4
sizeof int ** = 4
定义一个重写 printf 的函数,
int test_printf(const char *format, ...)
再定义一个结构体,在main中定义一个结构体变量,赋值,并传递给test_printf()函数,在test_printf中通过指针的移动进行访问
struct person{
char *name;
int age;
char score;
int id;
};//定义结构体main:
struct person per= {"www.100ask.org",21,'A',123456};
在main函数中向test_printf()传递三个参数,通过指针的移动进行访问,并将每个变量的地址打印
push_test("abcd",123,per); //传递参数
int test_printf(const char *format, ...)
{
char *p =(char *) &format; //将一个char型指针指向第一个参数的地址
int i;
struct person per1;
printf("p value :0x%x\n",p); //打印p的值,就是第一个参数的地址
printf("p addr :0x%x\n",&p);//打印p的地址
printf("arg1 : %s\n",format);//打印出第一个参数
printf("format addr :0x%x\n",&format);
printf("/-------------------------1\n");
p = p + (sizeof(char *));//将指针向上移动,移动第一个参数的大小
printf("p value :0x%x\n",p);//打印出现指针的值i = *((int *)p);//将p强制类型转换成指向int型的指针,并把指向的内容赋给变量i
printf("arg2 : %d\n",i);//打印出变量i
printf("&i = %p\n",&i);//打印出i的地址
printf("/-------------------------2\n");
p = p + sizeof(int);//再将指针向上移动,移动第二个参数的大小
per1 = *((struct person*)p);//将指针强制类型转换为指向结构体的指针,并将指向的内容赋给per1
printf("p value :0x%x\n",p);//打印出现在指针的值printf(" &per1.name = %p , pe1.name = %s\n" ,&per1.name,per1.name);
printf(" &per1.age = %p , pe1.age = %d\n" ,&per1.age ,per1.age );
printf("&per1.score = %p , pe1.score = %c\n" ,&per1.score,per1.score);
printf("&per1.id = %p , pe1.id = %d\n" ,&per1.id,per1.id);//打印出结构体变量的地址与值
使用32位编译器进行编译
gcc -m32 -o my_printf my_printf.c
p value :0xffb01210
p addr :0xffb011fc
arg1 : abcd
format addr :0xffb01210
/-------------------------1
p value :0xffb01214
arg2 : 123
&i = 0xffb011f8
/-------------------------2
p value :0xffb01218
arg3 : .name = www.100ask.org; .age = 21; .score = A; .id = 123456
&per1.name = 0xffb011c8 , pe1.name = www.100ask.org
&per1.age = 0xffb011cc , pe1.age = 21
&per1.score = 0xffb011d0 , pe1.score = A
&per1.id = 0xffb011d4 , pe1.id = 123456
由输出参数成功可见,参数在栈中由低地址到高地址依次排列。地址的间隔为各个数据类型所占的内存大小。变量的地址在堆栈中较低于参数的地址,也是依次排列。通过不断的向高地址移动指针,即可将参数不断地读入函数中。