分类: 嵌入式
2011-04-19 21:44:43
ARM_ARCH之指令
嘿嘿,趁热打铁,继续学习ARM指令…
WHY DO WE NEED TO KNOW THRE INSTRUCTION SET?
嵌入式系统需要初始化代码和中断例程;
所有的系统需要调试,可能在指令级别调试;
使用汇编能够获得更好的性能;
Some features of the ARM architecture are not available with compilers
这句话不理解….- -|||
CONDITIONAL EXECUTION AND FLAGS
在指令后面加上“S“,执行的时候,会在CPSR设置相应的bit。
CONDITION CODE
DATA PROCESSING INSTRUCTIONS
算术运算: ADD ADC SUB SBC RSB RSC
逻辑运算: AND ORR EOR BIC
比较: CMP CMN TST TEQ
数据移动: MOV MVN
算术运算默认情况下不设置CPSR相应的bit,除非加上S。
这些指令只能用于寄存器,不能用于内存。
语法:
<>内的项是必须的, {}内的项是可选的
Opcode 指令助记符,如LDR等;
Cond 执行条件,如EQ,NE等;
S 是否影响CPSR寄存器的值;
Rd 目标寄存器;
Rn 第一个操作数寄存器;
Shifter_operand 第二个操作数;
其指令编码格式如下:
SECOND OPERAND
第二个操作数是可选的,通常被用来对数据进行位移,位移的最大值不能超过5bit。
EXAMPLE:
add r0, r1, r1, lsl #2
先对r1寄存器中的值进行左移两位的操作,加入r1的值为5,位移之后变成20 (5*4),
再与r1相加赋值给r0,最后的结果是25;
一条指令中只有8BITS用来存储立即数,所以只能用特殊的方法,这里不介绍
详细的信息参考:http://blog.chinaunix.net/space.php?uid=20543672&do=blog&id=94265
你肯定会想要是存储大点的数据岂不是很麻烦,所以我们要使用LDR伪指令(pseudo-instruct)
LDR Rd, =const
FOR EXAMPLE
LDR R0, =0xFF -> MOV R0, #0xFF
LDR R0, =0x66666 -> LDR R0, [PC, #OFFSET]
………..
………..
DCD 0x66666
OFFSET的值取决去LDR与DCD之间有多少条指令,如果有两条,那么OFFSET=0;
注意真实的PC指向的是取指这条指令,而不是执行这条指令,但是在用软件调试时,编译器会掩盖这一切,PC指向执行这条指令。不管是三级流水线还是5级流水线,真实的PC=PC-8,所以才用了上面OFFSET=0。
LDR R0, [PC, #OFFSET]执行这条指令时,PC指向DCD,先到Literal pools取值。
Literal pools 汇编器用文字池保存一些常量以便于读取到寄存器中。汇编器把文字池放到每个部分的结尾,部分的结尾是指以END指令结尾或者AREA指令开始的后面部分。文字池会存放一些函数的入口地址以及常量,这点和栈有点像。- -
请参考:
http://blog.csdn.net/jiacky/archive/2009/06/05/4245194.aspx
BRANCH INSTRUCTIONS
B{L}{
子函数的调用需要在B后面加上L,可以实现24bits的地址最大偏移<+/-32M>。
实现子函数调用需要2步:
1> LR(r14)存储返回地址;
2> 跳转到子函数的入口地址。
用BX LR 或者 LDR PC, ADDR指令可以返回主调函数。
汇编的书写格式:
ARMEX是自己定义的
参考:http://www.cnblogs.com/hoys/archive/2010/12/01/1892578.html
SINGLE REGISTER DATA TRANSFER
Syntax:
LDR{
STR{
ADDRESS 是基地址加上偏移量来进行定位,但是不能定位到程序空间上,否则会出现异常现象。
EXAMPLE:
假如基地址是0x3000 0000,程序段存放在0x3000 0000~0x30000 0100之间,则不能定位到此区间对里面的数据进行写,否则会出现异常现象。
PRE OR POST INDEXED ADDRESSING
前变址寻址(PRE-INDEXED)
STR R0, [R1, #12] ;把R0寄存器中的值存储到R1+12的地址中。
后变址寻址(POST-INDEXED)
STR R0, [R1], #12 ;把R0寄存器中的值存储到R1中,然后R1=R1+12。
添加“!”会使寄存器中的值更新
STR R0, [R1, #12]! ;把R0寄存器中的值存储到R1+12的地址中,然后再R1=R1+12
LDR指令的用法也是一样。
MEMORY BLOCK COPYING
loop
LDR R2, [R5], #4
STR R2, [R7], #4
CMP R5, R6
BLT loop
LOAD AND STORE MULTIPLES
SYNTAX:
addressing modes:
LDMIA / STMIA increment after
LDMIB / STMIB increment before
LDMDA / STMDA decrement after
LDMDB / STMDB decrement before
SWP
寄存器与内存进行值交换。
SYNTAX:
SWP{
不能用C语言实现其功能,并且会设置相应的标志位。
SOFTWARE INTERRUPT(SWI)
产生一个异常陷入SWI硬件向量表,SWI处理程序会检查SWI数字从而决定相应何种操作。
SYNTAX:
SWI{
修改CPSR/SPSR寄存器的值
MRS r0,CPSR ; read CPSR into r0
BIC r0,r0,#0x80 ; clear bit 7 to enable IRQ
MSR CPSR_c,r0 ; write modified value to ‘c’ byte only
在用户模式中,不能改变CPSR的控制位,只能改变条件标志。在其他模式中可获得整个CPSR。
在用户模式中,不能访问SPSR,因为它不存在。