欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

arm裸机开发

程序员文章站 2022-07-14 15:18:41
...

GNU常用工具

GNU组织不仅给我们带来了许多开源软件 工程,还带来了强大的GNU编译工具

  • 预处理器 cpp
  • C编译器 gcc
  • C++编译器 g++
  • 汇编器 as
  • 链接器 ld
  • 二进制工具集 objcopy、objdump、……

1、nm:符号显示器

$nm -n main_elf
  • 第一列为符号地址
  • 第二列为符号所在段
  • 第三列为符号名称
    arm裸机开发
描述
b/B .bss(b静态/B非静态)未初始化变量
d/D .data(d静态/D非静态)已初始化变量
r/R .rodata(r静态/R非静态)只读数据段
t/T .text(t静态/T非静态)函数
A 不可改变的绝对值
C .o中未初始化非静态变量
N 调试用的符号
U 表示符号只有声明没有定义

1.1、nm符号显示器总结:

  • 静态变量和非静态的全局变量,所分配的段只与其是否 初始化有关,如果初始化了则被分配 在.data段中,否 则在.bss段中
  • 函数无论是静态还是非静态的,总是被分配在.text中, 小写t表示静态,大写T表示非静态
  • 函数内的局部变量由于是分配在栈上的,所以在nm中是 看不到他们的

2、objdump:信息查看器

  • 查看所有段信息 $objdump -h main_elf
  • 查看文件头信息 $objdump -f main_elf
  • 查看反汇编 $objdump -d main_elf
  • 查看内嵌反汇编 $objdump -S -d main_elf
  • 可以查看有哪些段和段里面的信息 $objdump -s main_elf
    arm裸机开发

3、objcopy:段剪辑器

剪除elf格式信息,这样才能在裸机状态下执行

  • 去除elf格式信息 $objcopy -O binary -S main_elf main.bin

程序的编译链接过程

最后一步是将目标文件交给链接器链接生成 可执行文件

  • gcc -E -o main.i main.c
  • gcc -S -o main.S main.i
  • gcc -c -o main.o main.S
  • gcc -o main_elf main.o

1、什么是链接

将所用到的文件, 吧相应的代码放到相应的段里面,并给每个段安排一个起始地址;
arm裸机开发
arm裸机开发

  • 用户通常并不直接参与链接过程
  • 一个标准应用程序通常都由链接器采用默 认链接脚本(arm-linux-ld --verbose)将“用户 程序”和“库”共同链接生成可执行程序
  • 假如不采用系统给定的默认链接脚本,我 们应该怎样进行链接?
ld -o main main.o

结论:

  • 链接过程中需要一个标号(_start)作为程序入口
  • 标号(_start)的作用是:将用户程序从汇编带到了C语 言程序入口,即main()函数,从此开始我们的应用程序 之旅
  • start标号所在的汇编文件在编译工具链下面: 4.3.2/arm-none-linux-gnueabi/libc/usr/lib/crt1.o
  • 如果没有crt1.o等标准库文件,我们可以自己实现_start入口,或者重新指定 一个新的入口
手动链接并生成可执行文件过程如下:
  • 直接通过参数指定程序入口和段地址: arm-linux-ld -Ttext=0x30000 -Tdata=0x40000 -e main -o app head.o main.o
  • 通过链接脚本来指定程序入口和段地址: arm-linux-ld -Tapp.lds -o app head.o main.o
//连接文件app.lds为: 
ENTRY(main) 
SECTIONS 
{
	//“*”号指所有目标,可以指定.o目标文件,多个用空格隔开 
	.=0x30000;//“.”指的是当前位置 
	.text:{*(.text)} 
	.=0x40000; 
	.data:{*(.data)} 
	.bss:{*(.bss)} 
}

为什么需要我们自己完成链接过程?

裸机工程构建及调试

1、裸机程序完整编译过程:

案例,打印 hello IoT

int main()
{
	char *str = "\nhello IoT";
	char *p = 0xc00a1020;
	int i = 11;
	while(i--)
	{
		*p = *str++;
	}
	return 0;
}

裸机程序完整编译过程:

arm-linux-gcc -c -o t.o t.c	//只编译不连接
arm-linux-ld -o t t.o -e main -Ttext=0x47000000		//手动连接
arm-linux-objcopy -O binary -S t t.bin

使用超级终端:
设置串口默认下载地址:
setenv loadaddr 0x47000000
查看设置的环境变量:printenv
上传.bin文件:loadb
运行:go 0x47000000