arm 点滴
arm学了几天,主要是体系结构和汇编部分,小总结一下:
1 realview的编辑器实在是很差劲,用惯了vim的,就想敲j k h l,好不习惯啊,可恶的是连自动缩进都没有。
2 realview写程序之前一定要设置好工程选项,比如程序下到哪里,ram的地址,rom的地址,sct连接脚本,调试脚本都要配置好。这些信息又是怎么得到的呢,通过看芯片说明,内存和地址分配部分。
3 arm的立即数是有要求的,并不是所有的立即数都合法,这是因为指令长度固定决定的,每个立即数由一个8位的常数循环右移偶数位得到。其中循环右移的位数由一个4位二进制的两倍表示。如果必须要用到非法的立即数,可以用ldr r0, =0x00100100这种格式。
4 用h-jtag与开发板连接调程序时,如果板子上没有跑操作系统,那么连接脚本里的地址都是物理地址,如果选得下载地址是ram上,cpu直接在ram上取指令,如果在flash上,就在flash上取指令,如果开了cache,则可能在cache上取指令。数据存储器指定了栈数据的地址。
5 直接在内存上跑程序时,有时候要点两次调试才行,貌似是realview的一个bug。
6 中断向量表的建立有两种方式,一种是在对应的0x0开始的地址放一条B指令,(一定是B,不能BL),第二种是以pc为目标的ldr指令,如果用这种方式,紧挨着的下面的存储区域要放置需要转到的地址,这样可以实现大于32M的跳转。
7 因为arm的所有指令都可以是带条件执行的,这给条件语句的实现带来了很大的便利,不用写复杂的判断结构。
8 一般arm都是用的满递减栈,所以常用ldmfd 和stmfd指令。
9 一定要搞清楚r12 r13 r14 r15 spsr这几个寄存器的用途,要牢记r0 r1 r2 r3 通常用作函数传参,什么时候该压栈保护寄存器。
10 非叶子函数一定要注意特殊寄存器的保护,包括中断处理函数(是否是可重入中断,可否中断嵌套)。
11 realview汇编的格式要求非常严格,比如equ 和dcd伪指令,必须顶格写。让我想起了makefile
12 arm 中移位运算和算术运算的优先级与c中的不同。 为了对齐,开头一句preserve8是常用到的。
13 h-jtag 选项如果没有的话,要先运行hjtat-conf文件,把keil安装目录的tools.ini加进去。
14 先前对合时该对寄存器进行备份保护一直有疑问,感觉有时保护了,有时没有保护,今天仔细思考总结了一下。从局部和全局变量的角度理解,r0-r12(fiq是r0-r7), pc, cpsr对每种模式来说都只有一个,所以一定是全局,这样在使用他们时,如果不希望影响上一个状态或者上层函数的值,就要备份,压栈或者把pc, cpsr推入r14(lr),spsr中。sp指针和r13-r14(fiq模式是r8-r14),spsr寄存器,虽然有备份,但是这是针对模式切换的备份,在同一种模式中,这些寄存器也是全局的,比如usr状态下的所有函数调用,用的都是同一个sp,这时如果被调函数不希望改变调用函数的这些寄存器的值,又要用到这些寄存器,还是要备份它们。规范约定,r0-r3作为函数间传递的参数,被调函数不必保存和恢复他们的值,也就是说把他们当做全局的变量来用。r4-r12作为局部变量,使用到时先备份,用完恢复。这条规范对于简单调用(如整个程序中全部是叶子函数的情况)比较适用。进入异常模式时cpsr自动存入spsr,所以movs pc, lr可以返回到原状态。bl跳转是把pc压入lr但是没有把cpsr压入spsr,所以仅适用于同一模式下的跳转。对应的返回仅需把r14赋给pc 直接mov pc, r14 或者 bx r14。从异常模式中返回的方式还可能是ldmfd sp!, {r0-r3, r12, pc}^, 关键是后面的^保证cpsr;
暂时想到这么多。