寄存器分配:
1. 遵循ATPCS调用规则的函数,必须保护被调用寄存器r4~r11的值。同时规定堆栈应是8字节边界对齐的,以下是寄存器压栈和出栈的模板:
routine_name
STMFD sp!, {r4-r12, lr} ;r12的使用是不需要压栈保存的,这里压栈仅仅是为了保证8字节边界对齐!
;body of routine
;the fourteen registers r0 - r12 and lr are available
LDMFD sp!, {r4-r12, pc} ;符合 ! 表示sp值随入/出栈(数据传送)而改变,即sp是数据出/入栈的起始或基地址
多寄存器传送指令:
1. 多寄存器传送load-store指令寻址模式读取处理大块连续数据:IA / IB / DA / DB : (基地址)执行后/前 增加/减少
2. 更新基地址的load-store指令对:用于临时保存一组寄存器,使用完毕后再恢复它们的场合
STMIA --- LDMDB; STMIB --- LDMDA; STMDA --- LDMIB; STMDB --- LDMIA
如:STMIB r0!, {r1-r3} ... LDMDA r0!, {r1-r3} --- 不但恢复r1~r3, r0的地址也恢复了。
3. 堆栈操作寻址方式---在ATPCS标准,堆栈被定义为递减满堆栈,因此LDMFD和STMFD指令分别用来支持pop和push功能。
处理器模式寄存器cpsr的条件标志(MSB 5-bit):
1. 由比较指令或带有后缀S的ALU操作结果来设置,比如,如果一条SUBS减法指令产生了一个结果为0的寄存器值,则cspr中的Z标志位被置位(通过判断这个位可以做随后的相应操作)。
2. 大多数指令都有一个条件属性,再根据条件标志位的情况,决定内核是否执行该指令。执行前,处理器比较该条件属性和cpsr的条件标志位,匹配则执行,否则被忽略。条件属性作为指令助记符的后缀被编码进指令,如EQ,NE,MI,PL,HI,LS,GE,LT,GT,LE,AL...(24)。
常用指令操作方式:
1. 移位指令:
MOV r7, r5 ;r5可以是立即数,寄存器,或桶型移位器处理过的结果
MOV r7, r5, LSL #2 ;(LSL, LSR, ASR, ROR, RRX)
MOVS r0, r1, LSL #1 ;因为指令助记符中有S出现,故cpsr的C标志位会被更新
2. 算术指令:
SUB r0, r1, r2
RSB r0, r1, #0 ;r0 = 0-r1 逆向减法,用于对某数取反
SUBS r1, r1, #1 ;带助记符的减,很方便的实现循环计数器的递减操作,cpsr的Z和C位被影响
ADD r0, r1, r1, LSL #1 ;r1<<1 + r1, 及r0 = r1*3
3. 逻辑指令:
ORR r0, r1, r2
BIC r0, r1, r2 ;<==>r0 = r1 AND NOT(r2), 常用于改变cpsr中的中断屏蔽位
4. 比较指令:
把一个寄存器与一个32位值做比较,比较结果更新cpsr的标志位,但不影响参与比较的其他寄存器。设置标志位后,其他指令可通过条件执行来改变程序的执行流程。对于比较指令,不需要使用S后缀就可以改变标志位。
r0 = 4 r9 = 4 CMP r0, r9 ;POST cpsr=nZcvqiFt_USER
本质上是一个不返回运算结果的减法指令,类似,TST是一个没有保存结果的逻辑"与"操作,TEQ是一个逻辑"异或"操作,每个操作部需要保存运算结果,只根据结果影响cpsr位。
5. 乘法指令:
MUL r0, r1, r2 ;32位乘
MLA r0, r1, r2 ;32位乘累加,r0 = r0 + r1*r2
SMLAL ;长整形有符合乘累加
SMULL ;长整形有符合乘
UMLAL ;长整形无符合乘累加
UMULL r0, r1, r2, r3 ;长整形无符合乘 [r1, r0] = r2*r3
6. 分支指令: (B, BL, BX, BLX)
B 跳转 pc=lable
BL 带返回的跳转 pc=lable lr=BL后面的第一条指令地址
BL subroutine
CMP r1, #5
MOVEQ r1, #0
...
subroutine
<子程序代码>
MOV pc, lr ;返回
7. load-store指令类型一:单寄存器传送指令
LDR r0, [r1, #4] ;前变址,r1不变
LDRB r0, [r1], #4 ;后变址,r1=r1+4
LDRH r0, [r1, #4]! ;回写型前变址,r0=[r1+4], r1=r1+4
8. load-store指令类型二:多寄存器传送指令 (IA, IB, DA, DB)
LDMIA = r0!, {r1-r3} ; 见上面多寄存器传送指令
9. load-store指令类型三:交换指令
SWP r0, r1, [r2] ;字交换,内存r2地址处值读到r0寄存器,r1寄存器值存入r2所指地址处。可以字节交换SWPB
10. 常量的装载:
ARM增加2条伪指令,用于把一个32位的常量送入寄存器
LDR Rd, constant ;常量装载伪指令<==>编译器转化为 MOV r0, #constant
ADR Rd, lable ;地址装载伪指令
MVN Rd, #constant ;实际多使用这个,效率高些
11. 条件执行:
指令只有当条件代码标志与给定的条件匹配时才执行,主要依赖两部分:条件码和条件标志,前者在指令中,后者在cpsr中。分析下例:
while(a!=b)
{
if(a>b) a -= b; else b -= a;
}
//++仅使用可条件执行的分支指令:
gcd
CMP r1, r2
BEQ complete
BLT lessthan
SUB r1, r1, r2
B gcd
lessthan
SUB r2, r2, r1
B gcd
complete
...
//++全部使用条件执行:
gcd
CMP r1, r2
SUBGT r1, r1, r2
SUBLT r2, r2, r1
BNE gcd
(秩名) |