这两天参加了一个编写操作系统的项目,因为要做很多底层的东西,而且这个操作系统是嵌入式的,所以开始学习ARM汇编,发现ARM汇编和一般PC平台上的汇编有很多不同,但主要还是关键字和伪码上的,其编程思想还是相同的。现将一些学习感悟部分列出来,希望能给有问题的人一点帮助。
AREA JumpTest,CODE,READONLY
CODE32
num EQU 4
ENTRY
start
MOV r0, #4
MOV r1, #3
MOV r2, #2
MOV r3, #0
CMP r0, #num
BHS stop
ADR r4, JumpTable
CMP r0, #2
MOVEQ r3, #0
LDREQ pc, [r4,r3,LSL #2]
CMP r0, #3
MOVEQ r3, #1
LDREQ pc, [r4,r3,LSL #2]
CMP r0, #4
MOVEQ r3, #2
LDREQ pc, [r4,r3,LSL #2]
CMP r0, #1
MOVEQ r3, #3
LDREQ pc, [r4,r3,LSL #2]
DEFAULT
MOVEQ r0, #0
SWITCHEND
stop
MOV r0, #0x18
LDR r1, =0x20026
SWI 0x123456
JumpTable
DCD CASE1
DCD CASE2
DCD CASE3
DCD CASE4
DCD DEFAULT
CASE1
ADD r0, r1, r2
B SWITCHEND
CASE2
SUB r0, r1, r2
B SWITCHEND
CASE3
ORR r0, r1, r2
B SWITCHEND
CASE4
AND r0, r1, r2
B SWITCHEND
END
程序其实很简单,可见我有多愚笨!还是简要介绍一下这段代码吧。首先用AREA伪代码加上CODE,表明下面引出的将是一个代码段(于此相对的还有数据段DATA),ENTRY 和END成对出现,说明他们之间的代码是程序的主体。start段给寄存器初始化。ADR r4, JumpTable一句是将相当于数组的JumpTable的地址付给r4这个寄存器。
stop一段是用来是程序退出的,第一个语句“MOV r0,#0x18”将r0赋值为0x18,这个立即数对应于宏angel_SWIreason_ReportException。表示r1中存放的执行状态。语句“LDR r1,=0x20026”将r1的值设置成ADP_Stopped_ApplicationExit,该宏表示程序正常退出。然后使用SWI,语句“SWI 0x123456”结束程序,将CPU的控制权交回调试器手中。
在JumpTable表中,DCD类型的数组包含四个字,所以,当实现CASE跳转的时候,需要将给出的索引乘上4,才是真正前进的地址数。
再看一个用汇编实现冒泡排序的例程:
AREA Sort,CODE,READONLY
ENTRY
start
MOV r4,#0
LDR r6,=src
ADD r6,r6,#len
outer
LDR r1,=src
inner
LDR r2,[r1]
LDR r3,[r1,#4]
CMP r2,r3
STRGT r3,[r1]
STRGT r2,[r1,#4]
ADD r1,r1,#4
CMP r1,r6
BLT inner
ADD r4,r4,#4
CMP r4,#len
SUBLE r6,r6,#4
BLE outer
stop
MOV r0,#0x18
LDR r1,=0x20026
SWI 0x123456
AREA Array,DATA,READWRITE
src DCD 2,4,10,8,14,1,20
len EQU 7*4
END
用汇编实现循环需要跳转指令,但是因为ARM系统只有一个CPSR寄存器,所以要实现双重循环还是有些难度。上面这个代码还是有相当大的借鉴意义。程序不难读懂,和C语言的冒泡排序基本思路是完全一样的。