浅析arm汇编中^、!、cxsf符号和movs等指令使用学习-之1
来源:互联网 发布:回看 网络电视 编辑:程序博客网 时间:2024/05/16 00:25
from:http://blog.chinaunix.net/uid-20564848-id-72822.html
文章来源:http://gliethttp.cublog.cn
.macro restore_user_regs
ldr r1,[sp, #S_PSR]
ldr lr,[sp, #S_PC]! @!用来控制基址变址寻址的最终新地址是否进行回写操作,
@ 执行ldr之后sp被回写成sp+#S_PC基址变址寻址的新地址
msr spsr,r1 @ 把cpsr的值保存到spsr中
ldmdb sp,{r0 - lr}^ @ lr=[sp-1*4],r13=[sp-2*4],r12=[sp-3*4],......,r0=[sp-15*4]
@ 因为没对pc赋值,所以^的表示将数据恢复到User模式的[r0-lr]寄存器组中[gliethttp]
mov r0,r0
add sp,sp,#S_FRAME_SIZE- S_PC
movs pc,lr
.endm
其他指令正在学习中[随时补充gliethttp]
-----------------------------
1.ldr ip,[sp],#4 将sp中内容存入ip,之后sp=sp+4;
ldr ip,[sp,#4] 将sp+4这个新地址下内容存入ip,之后sp值保持不变
ldr ip,[sp,#4]!将sp+4这个新地址下内容存入ip,之后sp=sp+4将新地址值赋给sp
str ip,[sp],#4 将ip存入sp地址处,之后sp=sp+4;
str ip,[sp,#4] 将ip存入sp+4这个新地址,之后sp值保持不变
str ip,[sp,#4]!将ip存入sp+4这个新地址,之后sp=sp+4将新地址值赋给sp
-----------------------------
2.movs r1,#3;movs将导致ALU被更改,因为r1赋值非0,即操作结果r0非0,所以ALU的Z标志清0
bne 1f ;因为Z=0,说明不等,所以向前跳到标号1:所在处继续执行其他语句
-----------------------------
3.LDM表示装载,STM表示存储.
LDMED LDMIB 预先增加装载
LDMFD LDMIA 过后增加装载
LDMEA LDMDB 预先减少装载
LDMFA LDMDA 过后减少装载
STMFA STMIB 预先增加存储
STMEA STMIA 过后增加存储
STMFD STMDB 预先减少存储
STMED STMDA 过后减少存储
注意ED不同于IB;只对于预先减少装是相同的.在存储的时候,ED是过后减少的.
FD、ED、FA、和 EA 指定是满栈还是空栈,是升序栈还是降序栈.
对于存储STM而言
先加后存 FA 姑且这么来记,先加(firstadd),存数据
后加先存 EA 姑且这么来记,存数据,后加endadd
先减后存 FD 姑且这么来记,先减first dec,存数据
后减先存 ED 姑且这么来记,存数据,后减enddec
然后记忆LDM,LDM是STM的反相弹出动作,所以
因为是先加后存,所以后减先取 FA 就成了与STM对应的取数据,后减
因为是后加先存,所以先减后取 EA 就成了与STM对应的先减,取数据
因为是先减后存,所以后加先取 FD 就成了与STM对应的取数据,后加
因为是后减先存,所以先加后取 ED 就成了与STM对应的先加,取数据
我想通过上面的变态方式可以比较容易的记住这套指令[gliethttp]
一个满栈的栈指针指向上次写的最后一个数据单元,而空栈的栈指针指向第一个空闲单元.
一个降序栈是在内存中反向增长(就是说,从应用程序空间结束处开始反向增长)而升序栈在内存中正向增长.
其他形式简单的描述指令的行为,意思分别是
IA过后增加(Increment After)、
IB预先增加(Increment Before)、
DA过后减少(Decrement After)、
DB预先减少(Decrement Before).
RISC OS使用传统的满降序栈.在使用符合APCS规定的编译器的时候,它通常把你的栈指针设置在应用程序空间的
结束处并接着使用一个FD(满降序-Full Descending)栈.如果你与一个高级语言(BASIC或C)一起工作,你将别无选择.
栈指针(传统上是R13)指向一个满降序栈.你必须继续这个格式,或则建立并管理你自己的栈.
-----------------------------
4.
teq r1,#0 //r1-0,将结果送入状态标志,如果r1和0相减的结果为0,那么ALU的Z置位,否则Z清0
bne reschedule//ne表示Z非0,即:不等,那么执行reschedule函数
-----------------------------
5.使用tst来检查是否设置了特定的位
tst r1,#0x80 //按位and操作,检测r1的0x1<<7,即第7位是否置1,按位与之后结果为0,那么ALU的Z置位
beq reset //如果Z置位,即:以上按位与操作结果是0,那么跳转到reset标号执行
-----------------------------
6.'^'的理解
'^'是一个后缀标志,不能在User模式和Sys系统模式下使用该标志.该标志有两个存在目的:
6.1.对于LDM操作,同时恢复的寄存器中含有pc(r15)寄存器,那么指令执行的同时cpu自动将spsr拷贝到cpsr中
如:在IRQ中断返回代码中[如下为ads环境下的代码gliethttp]
ldmfd {r4} //读取sp中保存的的spsr值到r4中
msr spsr_cxsf,r4 //对spsr的所有控制为进行写操作,将r4的值全部注入spsr
ldmfd {r0-r12,lr,pc}^//当指令执行完毕,pc跳转之前,将spsr的值自动拷贝到cpsr中[gliethttp]
6.2.数据的送入、送出发生在User用户模式下的寄存器,而非当前模式寄存器
如:ldmdb sp,{r0- lr}^;表示sp栈中的数据回复到User分组寄存器r0-lr中,而不是恢复到当前模式寄存器r0-lr
当然对于User,System,IRQ,SVC,Abort,Undefined这6种模式来说[gliethttp]r0-r12是共用的,只是r13和r14
为分别独有,对于FIQ模式,仅仅r0-r7是和前6中模式的r0-r7共用,r8-r14都是FIQ模式下专有.
-----------------------------
7.spsr_cxsf,cpsr_cxsf的理解
c - control field mask byte(PSR[7:0])
x - extension field mask byte(PSR[15:8])
s - status field mask byte(PSR[23:16)
f - flags field mask byte(PSR[31:24]).
老式声明方式:cpsr_flg,cpsr_all在ADS中已经不在支持
cpsr_flg对应cpsr_f
cpsr_all对应cpsr_cxsf
需要使用专用指令对cpsr和spsr操作:mrs,msr
mrs tmp,cpsr //读取CPSR的值
bic tmp,tmp,#0x80 //如果第7位为1,将其清0
msr cpsr_c,tmp //对控制位区psr[7:0]进行写操作
-----------------------------
8.cpsr的理解
CPSR = Current Program Status Register
SPSR = Saved Program Status Registers
CPSR寄存器(和保存它的SPSR寄存器)
(上图)
N,Z,C,V称为ALU状态标志
N:如果结果是负数则置位
Z:如果结果是零则置位
C:如果发生进位则置位
V:如果发生溢出则置位
I:置位表示禁用IRQ中断,清0表示使能IRQ
F:置位表示禁用FIQ中断,清0表示使能FIQ
T:置位表示系统运行在Thumb态,清0表示运行在ARM态
M[4:0]:
10000 User模式,和System系统模式一样
10001 FIQ模式
10010 IRQ模式
10011 SVC超级管理模式
10111 Abort数据异常模式
11011 Undefined未定义指令模式
11111 System系统模式,和User模式一样
举例:
ands r2,r2,#7 使用运算结果改变标志位,如果运算结果r2=0,那么Z置位,EQ相等判断成立
subs r2,r2,#1 使用运算结果改变标志位,如果运算结果r2=0,那么Z置位,EQ相等判断成立
beq wordcopy
-----------------------------
9.指令后缀和条件判断
(上图)
EQ : 等于
NE : 不等
CS : 无符号>=
CC : 无符号<
MI : 负数
PL : 非负[>=0]
VS : 溢出
VC : 无溢出
HI : 无符号>
LS : 无符号<=
GE : 有符号>=
LT : 有符号<
GT : 有符号>
LE : 有符号<=
AL : 总是[默认]
对于arm汇编指令,可以参考linux内核的arch/arm目录,那里的汇编指令很丰富[gliethttp_20080603]
__CopyFromStart
; ldr r3, [r9], #4
; str r3, [r7], #4
; sub r8, r8, #4
ldrb r3, [r9], #1
strb r3, [r7], #1
sub r8, r8, #1
cmp r8, #0
bgt __CopyFromStart
b __JumpToBootImage
__JumpToBootImage
MOV pc, r0
- 浅析arm汇编中^、!、cxsf符号和movs等指令使用学习-之1
- ARM汇编中^、!、cxsf符号和movs等指令使用
- ARM汇编中^、!、cxsf符号和movs等指令使用
- ARM汇编中^、!、cxsf符号和movs等指令使用
- Arm汇编学习笔记(五)——MOVS及^符号等
- Arm汇编学习笔记(五)——MOVS及^符号等
- ndk内联汇编的使用之arm指令学习和调试
- 浅析arm汇编中指令使用学习
- ARM汇编指令学习之开篇
- 在实例中学习arm汇编指令
- ARM中MRS和MSR汇编指令
- ARM 汇编指令学习:[1]ARM指令寻址方式
- Win32 汇编 - 串指令: MOVS*、CMPS*、SCAS*、LODS*、REP、REPE、REPNE 等
- 详细学习ARM 汇编指令1
- 汇编指令:CLD STD MOVS LODS STOS
- ARM汇编中LDR伪指令和LDR指令
- ARM汇编中ldr伪指令和ldr指令
- ARM汇编中ldr伪指令和ldr指令
- Cognos测试数据源XQE-JDB-0004错误的解决方案
- R语言中的模型公式与图表
- zookeeper分布式锁(六)
- 常见的各种排序
- (Xilinx)FPGA中LVDS差分高速传输的实现
- 浅析arm汇编中^、!、cxsf符号和movs等指令使用学习-之1
- 冒泡排序
- Android - 线程同步
- Spring+Struts2, 将框架的配置文件整合起来
- 海量数据处理面试题-①笔记
- 2.纹理贴图
- 查看服务器型号
- 随笔
- 实现自己的http server