_start程序入口标号
1:我们的逻辑程序是直接运行在UBOOT之上的,
2:裸机程序是没有任何库函数的,包括printf
3:裸机程序时直接操作寄存器的
4:裸机程序的入口是_start()函数
连接器会检查是否有_start函数存在,而编译器和连接器是按照函数定义的
顺序来排列代码,所以_start函数作为整个bin文件的入口,类似于main函数,必须定义在所有
其他函数的前面
void _start()
{
}
-Ttext连接地址作用
裸机程序未加链接地址时,只能使用text代码段,如果裸机程序中使用出现了跨端操作(使用text端段以外的段:rodata,data,bss段),必须在链接时手工指定连接地址为实际的运行地址,及uboot命令中go命令运行裸机程序的地址#go 40000000
加了连接地址-Ttext以后才可以跨端操作,可以使用text代码段还可以使用text以外段
如何使用uboot中的函数
1:首先你的uboot必须编译连接了,已经烧写到开发板了
2:这样你的uboot代码里就会生成一个函数连接地址System.map文件,获得uboot中所有函数虚拟地址,由arm-linux-nm命令重定向导出的符号表。
System.map文件内容
c3e00000 T _start 都是虚拟地址,映射后的地址,对应0x43e00000地址
c3e00020 t _undefined_instruction
c3e00024 t _software_interrupt
c3e00028 t _prefetch_abort
c3e0002c t _data_abort
c3e00030 t _not_used
c3e00034 t _irq
c3e00038 t _fiq
c3e00040 t _TEXT_BASE
c3e00044 T _armboot_start
c3e00048 T _bss_start
c3e0004c T _bss_end
c3e00050 T IRQ_STACK_START
c3e00054 T FIQ_STACK_START
c3e00058 t start_code
………
c3e11ad0 T printf
//定义函数指针
static int (*printf)(const char *format,...) = (int (*)(const char *format,...))0xc3e11ad0
void _start()
{
printf("hello");
}
#makefile
TGT := boot.o
OBJC := test.o
CROSS_COMPILER := arm-linux-
CC := $(CROSS_COMPILER)gcc
OBJCOPY := $(CROSS_COMPILER)objcopy
CFLAGS := -ffreestanding
LDFLAGS : -static -nostartfiles -Ttext=0x40000000
all:
$(CC) $(CFLAGS) -c $(OBJC:.o=.c)#替换后缀,编译生成a.out
$(CC) $(LDFLAGS) $(OBJC)
$(OBJCOPY) -O binary a.out $(TGT:.o=.bin)
clean:
$(RM) a.out $(OBJC) $(TGT:.o=.bin)