嵌入式开发43天(ARM汇编的常用指令,编码格式,立即数合法的条件,中断的响应过程)

一、常见的ARM开发环境

1、ADS1.2  ---> ARM7 + ARM9 + ARM9E

2、MDK5.1  ---> ARM7 + ARM9 + ARM9E + Cortex-M0M3M4

3、IAR --->ARM7 + ARM9 + ARM9E + Cortex-M0M3M4

4、RVDS --->支持ARM7ARM94ARM10ARM11Cortex等全系列ARM内核

5、GNU --->arm-linux-gcc

看到这里就有有人会问,为啥不用RVDS做开发,这个原因请淘宝一下~

二、ARM汇编指令的编码格式

RISC架构:

1)每条汇编指令编译成的机器码是等长的(ARM32bitsTHUMB16bits--->执行的效率高,代码的密度低。

2)指令数少,绝大部分指令是重复使用

ARM汇编指令的编码格式:



条件码:

ARM汇编指令的后面都可以加条件,条件的判断依据---->CPSR(NZCV)


三、ARM汇编指令

1、数据处理指令

     完成通用寄存器(R0~R15)与立即数之间的数据运算及处理。

1)算术运算指令

ADD R1, R2, #10 //R1=R2+10


SUB R3,R2,R1 //R3=R2-R1


AND R1,R1,#0x3// R1=R1&0x3


ORR R1,R1,#3 // R1=R1 | 0x3


BIC R1,R1,#3 //R1=R1&~3


EOR R1,R1,#3 //立即寻址R1=R1^3


RSB R3,R2,R1 //寄存器寻址 R3=R1-R2  逆向减法

 

错误的写法:

ADD R2, #10, #20

SUB R1,#10,R2

 

 

2)比较指令 ---->不需要加”S”,会自动影响条件码标志位

CMP R1, #10  //类似于 SUBS R2, R1, #10

TEQ R1, #10

TST R1, #8

 

3)传输指令

MOV  R1, #10

MVN  R1, #10

 

注意:

在数据处理指令中,立即数有要求的,并不是所有的立即数都是合法的。例如,以下ARM汇编指令是非法,原因是立即数不合法。

ADD R5,R5,#0x123

MOV R5, #0x345

CMP R6, #0x678

 

立即数合法的条件:

1)如果立即数是小于2560x100)的,即该立即数可以用8bits的二进制数描述。

2)如果立即数大于256,但是该立即数经过循环左移偶数位,可以得到一个小于256的数,则该立即数合法。

例:BIC R1, R1, #0xffff  //不合法

 

解决方法1

BIC R1, R1, #0xff

BIC R1, R1, #0xff00

 

解决方法2

LDR R0, =0xffff  //mov r0, #0xffff不合法

BIC R1,R1,R0


 

2、数据加载和数据存储指令


完成通用寄存器和存储器之间的数据传递。通过一个地址来访问该地址下的数据,相当于C语言的指针。

LDR ---->loader 将一个地址下的数据加载到通用寄存器,采用的寻址方式是间接寻址。相应于C语言的指针。

STR ----->storeloader的反方向。

例:

LDR R0, =0xe0200280  //LDRARM汇编伪指令,实现了将0xe0200280传到R0

LDR R1, [R0] //LDRARM汇编指令,将0xe0200280地址下的数据加载给R1

LDR R2, [R0, #4] //0xe0200280+4地址下的数据加载给R2。基址変址寻址

 

LDR R1,[0xe0200280] //错误

 

STR R2, [R0] //R2的内容存储到R0的地址下。

注意:

LDRSTR是字类型的数据的加载和存储。

LDRBSTRB是字节类型数据的加载和存储

LDRHSTRH是半字节类型数据的加载和存储

 

----------------------------------------------------------------------


3、跳转指令--->分支指令

B  ----> 直接跳转,跳转的同时不保存返回地址。

BL -----> 在跳转之前保存返回地址到LRR14),然后在跳转

BX ---->带有工作状态切换的跳转。ARM状态<---->THUMB状态



注意:

受B跳转指令编码格式的限制,B在跳转的时候是范围限制的+-32MB


4、状态寄存器的访问指令

完成状态寄存器(CPSRSPSR)与通用寄存器(R0~R15)之间的数据传递

MSR  ---->   mov Status form Register

MRS  ---->   mov Register form Status

 

例:(思考)---->关闭IRQ中断

MRS R0, CPSR

ORR R0,R0,#(1<<7)

MSR CPSR, R0

 

不能如下:

ORR CPSR, CPSR ,#(1<<7)

 

5、乘法指令和乘加指令

完成通用寄存器指令的乘法或乘加。

MUL R1,R2,R3 //R1=R2*R3

MUL R1,R2,#4 //错误

 

MLA R1,R2,R3,R4 //R1=R2*R3+R4


6、批量的数据处理指令 --->栈的寻址

LDM --->多个LDR

STM --->多个STR

一般使用这些指令来操作stack

提出问题:stack的类型


7.中断响应的过程


8.数据交换指令

SWP R0R1[R2] //Load R0 with the word addressed by R2, and store R1 at R2.

相当于:

LDR R0,[R2]

STR R1, [R2]

 

SWP ---- 字类型数据的交换

SWPB ---- 字节类型数据的交换

=========================================================

四、ARM汇编伪指令

     ARM汇编伪指令相当于ARM汇编指令的集合。一个ARM汇编指令可能相当于几条ARM汇编指令及数据组成的一个序列。

     ARM汇编伪指令经过编译器编译后,后生成ARM汇编指令及数据。

 

1、NOP

MOV R0R0 替代

 

2、LDR

1)LDR R0, =0xe0200280

   首先将数据0xe0200280放到一个地址下,然后再通过数据加载指令(LDR)根据地址加载地址下的数据。由8个字节组成 4-->加载数据的汇编指令

                                 4-->存放数据  --->文字池(literal pool

2)LDR PC,=test

读取test符号的地址,送给PC,实现程序的跳转,用来替代B

=========================================================

三、ARM汇编伪操作

特别注意:ARM汇编伪操作是和开发环境有关系的。不同的开发环境,伪操作是有不同的。

.global  ---->声明一个符号是全局的。

.text  --->说明代码段

 

=========================================================

四、ARM汇编和C混合编程

1、汇编调用C

1)汇编源文件:

.text

.global _start //声明_start是全局的。这样编译器可以得到_start

 

_start:

//1.GPJ2_2 --->output ,GPJ2CON[11:8]=0001

LDR R0, =0xe0200280 //R0=0xe0200280

LDR R1, [R0] //0xe0200280地址下的内容,加载给R1

BIC R1,  R1,#(0xf<<8) //bit clear. R1 = R1 & (~0xf00) --->GPJ2CON[11:8]=0000

ORR R1,R1,#(1<<8) //按位或。R1=R1|0x100

STR R1,[R0] //将改写后的R1,写到0xe0200280地址下。str---store

 

main_loop:

//2.GPJ2_2 ouput 翻转

LDR R0, =0xe0200280

ldr R3,[R0,#4] //0xe0200280 +4

eor R3,R3,#(1<<2)  //R3=R3^0x4

str R3,[R0,#4]

MOV R0, #0x200000 // r0 -----> val

bl delay  //调用C的一个void delay(int val)

B main_loop

 

2)C源程序

void delay(int val)

{

int i;

for(i=val;i>0;i--);

}

 

 

2C调用汇编

1C的源程序

#define  GPJ2CON  (*(volatile unsigned int *)0xe0200280)

#define  GPJ2DAT  (*(volatile unsigned int *)0xe0200284)

extern void delay(int val);

void _start(void)

{

//GPJ2_2 --->output ,GPJ2CON[11:8]=0001

GPJ2CON &= ~(0xf<<8);

GPJ2CON |=  (0x1<<8);

while(1)

{

//GPJ2_2 ouput 翻转

GPJ2DAT ^= (1<<2);

delay(0x3000000);

}

}

 

2)汇编源程序

.global delay

delay:

SUBS R0,R0,#1

BNE delay

mov pc,lr


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

交叉编译之王 hahaha

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值