Chinaunix首页 | 论坛 | 博客
  • 博客访问: 366097
  • 博文数量: 50
  • 博客积分: 1495
  • 博客等级: 上尉
  • 技术积分: 805
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-21 14:19
文章分类

全部博文(50)

文章存档

2011年(47)

2010年(3)

分类: 嵌入式

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

这些指令只能用于寄存器,不能用于内存。

 

       语法:

      {}{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的值取决去LDRDCD之间有多少条指令,如果有两条,那么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}{}  Label

子函数的调用需要在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{}{}  Rd,

      STR{}{}  Rd,

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:

       {} Rb{!},

addressing modes:

LDMIA / STMIA           increment after

LDMIB / STMIB           increment before

LDMDA / STMDA      decrement after

LDMDB / STMDB      decrement before

 

SWP

寄存器与内存进行值交换。

SYNTAX

       SWP{}{B} Rd, Rm, [Rn]

不能用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,因为它不存在。

 

 

 

阅读(4459) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~