TQ210裸机编程(9)——实现printf
printf的原型如下
int printf(const char *format, ...);
它带有一个固定的参数format,紧接着是可选参数,所谓可选参数就是参数个数和类型都不固定,也可以没有。
C语言传参是从最后一个参数开始压栈的。
比如在ARM Linux系统下,ATPCS规定为递减堆栈,假设栈顶SP=0x24000000
假设有这么一个函数void foo(int a, int b, int c);
则参数a先压入栈,地址为SP-4=0x23FFFFFC;
紧接着b压入栈,地址为SP-4=0x23FFFFF8;
紧接着c压入栈,地址为SP-4=0x23FFFFF4;
标准C为我们提供了相关的宏来处理可选参数,这些宏在stdarg.h中定义。
在Linux发行版系统(比如ubuntu)中执行man stdarg可查看相关帮助信息。
root@zjh:/mnt/hgfs/E/cloud/embedded/my_code/tq210# man stdarg
#include <stdarg.h>
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
…………………
…………………
va_list ap:实际上就是int *ap;
va_start :初始化ap,使ap指向第一个可选参数,last就是调用函数的固定参数;
va_arg :解析出一个可变参数,并使ap指向下一个可选参数;
va_end :是ap指针无效
注意:在同一个函数中,每次对va_start的调用都必须有对应的va_end调用与之匹配。
通过man stdarg查询的帮助信息中有一个例子可以参考:
uart.bin: start.o clock.o uart.o main.oarm-linux-ld -Ttext 0xD0020010 -o uart.elf $^arm-linux-objcopy -O binary uart.elf $@arm-linux-objdump -D uart.elf > uart.dis%.o : %.carm-linux-gcc -c $< -o $@%.o : %.Sarm-linux-gcc -c $< -o $@clean:rm *.o *.elf *.bin *.dis
实验效果如下:
Uart Test for printft =
t = 1
t = 2
t = 3
t = 4
t = 5
t = 6
t = 7
t = 8
t = 9
t = 10
烧写过程见《TQ210裸机编程(5)——系统时钟配置》
转载请注明来源:http://blog.csdn.net/zjhsucceed_329/