1通过学习ARM汇编语言从而了解ARM处理器的工作原理。
2用汇编写Bootloader
在这里汇编的基本语法在《ARM嵌入式系统开发》里面已经写过了。这里就写一点需要特别注意的地方
我们学汇编,并不是要求用汇编写很多复杂的程序。那样不切实际,那些可以用更高一层的C来写。
7种寻址方式:
1立即数寻址 ADD r0,r0,#1
2寄存器寻址 ADD r0,r0,r1
3寄存器间接寻址 LDR r0,[r1]
4寄存器变址寻址 :前变址,自动变址,后变址
LDR r0,[r1,#4]
LDR r0,[r1,#4]!
LDR r0,[r1],#4
5堆栈寻址 我们一般用FD 满递减 LDM {sp}!,{r1-r4}
只用于堆栈
6块拷贝寻址
LDMIA LDMIB LDMDA LDMDB
7相对寻址
BL label 相对地址的寻址
LDR pc,label 或 MOV pc,label 绝对地址的寻址
具体指令不再做介绍了。补充一些:
1在例如 LDMFD sp!{r1-r5,pc}^
在加了pc的情况下 再加^表示把spsr拷贝到cpsr中。
2乘法指令一般不太用,效率低。即使要用也用位移来代替。
3AND与 用来志零 ORR或用来志1 EOR异或用来取反 BIC用来清位(BIC是比较数的哪一位是1哪一位就变0与AND相反)
而TST是没有结果寄存器的AND 并且改变cpsr TEQ是异或 CMP是减法。
接下来说本课的重点 armlinux的编译器gcc
在win下面用的是armcc,而我们的用gcc
1任何以冒号结尾的标识符都认为是一个标号,当标号为0到9的数字时是局部标号。在局部标号后加f表示引用标号的地方向前的标号
而加b则表示向后
例如: subs r0,r0,#1
bne 1f
2 。section伪操作来定义一个段,后加段名
汇编系统有预定义的段名 。text 代码段 。data初始化数据段 。bss未初始化数据段 (。bss要在text之前)
3定义入口点,默认下是start标号,也可以在连接脚本中用ENTRY(标志)来指示入口标志。连接脚本之后介绍。
.section .data
<...>
.section .bss
<...>
.section.text
.globl _start _start是全局的
_start: 代码从这开始执行。
4. .align 2(4,8,16) 对齐方式
.end 结束符 不加也不报错
.include 包含头文件
.global 定义一个全局符号
编译器 5大工具
arm-linux-as
arm-linux-gcc
arm-linux-ld
arm-linux-objcopy
arm-linux-objdump
介绍下一个ARM程序诞生的步骤。
1写程序
2编译成.o文件 用arm-linux-gcc -c link.s -o link.o
如果使用-S选项 对用C写的程序表示编译生成汇编文件
3编写连接脚本,编译成elf格式的文件:首先明确为什么要连接:有2点,1地址重定向。2写符号表。在gcc编译器中有内置的缺省的连接脚本,不过它是基于有操作系统的前提下的才能应用加载的。因为他是应用操作系统中内存的映射地址来连接的。而gnu编译器目标文件的个是是elf格式。它由若干的section组成。里面有。text段。data段。bss段。连接器的任务就是把多个目标文件的。text段。data段。bss段连接在一起。而连接脚本是告诉连接器从什么地址开始放至这些段。
如link。lds
ENTRY(begin)
SECTION
{
.=0x30000000; 表示目标代码开始的地址为0x30000000
.text :{*(.text)}
.data :{*(.data)}
.bss :{*(.bss)}
}
然后通过arm-linux-ld -nostadlib -o link.elf -Tlink.lds link.o main.o 生成elf格式的文件。其中nostadlib表示不连接系统的库,-T表示采用连接脚本。也可以使用-Ttext address;address表示执行区地址。
4生成2进制文件。2进制文件才可以在内存中加载
arm-linux-objcopy -o link.bin link.elf
5反汇编
还可以用objdump来实现反汇编
arm-linux-objdump -D link.elf > a.dis
arm-linux-objdump -D -b binary -m arm link.bin >a.dis
上一篇:第1课:S3C2440的烧写
下一篇:第3课: 点亮开发板led灯
推荐阅读最新更新时间:2024-03-16 15:03