基于ARM的汇编优化和基本指令用法【整理者】61ic.com
【提供者】rtweww 【详细说明】基于ARM的汇编优化和基本指令用法 寄存器分配: 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; SA --- LDMIB; SB --- 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 |
|