物联网之ARM体系结构及接口技术二(ARM指令)
ARM指令
搬移指令
movr13,#3
movr0,r1
movr0,r1,LSL#2@LSL#2表示逻辑左移两位,将r1左移两位之后的数值赋给寄存器r0
movr0,r1,LSR#2@LSR#2表示逻辑右移两位,将r1右移两位之后的数值赋给寄存器r0
mrsr0,cpsr@读取cpsr寄存器的值,赋给r0。注意特殊寄存器的读取使用mrs指令
msrcpsr,r0@将r0的值赋给cpsr。注意特殊寄存器的写入使用msr指令
条件执行
if (a==0)x=0;
if (a>0)x=x+3;
cmpr0,#0@比较r0与0是否相等
moveqr1,#0@mov是上面讲过的搬移指令,eq判断上一条指令执行的结果是否相等,如果相等,则将0赋值给r1
addgtr1,r1,#3@add是加法运算,gt判断cmp指令r0是否大于0,如果大于零,则将r1+3的值赋给r1
指令是如何存储的,如何被解析的?
写c代码--------------------------------->生成汇编代码------------------------->FLASH中最终存储机器指令(二进制)
文章图片
指令机器码(FLASH中最终存储机器指令(二进制)进行解析)
文章图片
当赋给寄存器的值过大时(一般大于255),就要使用伪指令对其赋值:ldr r0,=0x123456
逻辑指令
and r0,r1,#0xFF// r0 = r1&0xFF(与运算)
orr r3,r0,#0x0F// r3 = r0|0x0F (或运算)
bic r0,r0,#0x03// 清除r0中的0号位和1号位
tst r0,#0x20//测试第6位是否为0 ,为0则Z标志置1
cmp r1,r0//将R1与R0相减做比较,并根据结果设置CPSR的标志位
例:
? 使能中断和快速中断?
文章图片
mrsr0,cpsr
bicr0,r0,#0xc0(清零F位和I位)
msrcpsr,r0
? 判断当前工作状态是否是ARM状态,是则切换到user 工作模式?
文章图片
mrsr0,cpsr
tstr0,#0x20
andeqr0,r0,#0xFFFFFFE0 (低5位清零)
orreqr0,r0,#0x10
msreqcpsr,r0
算术指令
add r0,r1,r2//r0=r1+r2
subr0,r1,#3//r0= r1 - 3
subr0,r1,r2,LSL#1//r0=r1-(r2<<1)
mulr1,r2,r3//r1=r2*r3
跳转指令
bmain//跳转到标号为main地代码处
blfunc//保存下一条要执行的指令的位置到 LR寄存器,跳转函数func
//当跳转代码结束后,用MOV PC,LR指令跳回来
beqaddr//当CPSR寄存器中的Z条件码置位时,跳转到该地址处
bneaddr//当不等时,跳转到地址addr
例:
用汇编实现下面功能:
void main(void)
{
int ret=0;
func1(2);
while(1) {};
}
func1(int a)
{
if(a==2)
return func2(a);
else
return func3(a);
}func2(int a)
{
return a+3;
} func3(int a)
{
return a-1;
}
实现 延时1秒函数:
@delay fos 1 second
delay1s:
ldrr4,=0x3FFFF
loop_delay1s:
subr4,r4,#1
cmpr4,#0
bneloop_delay1s
delay1s_end:
movpc,lr
测验:
用汇编实现求最大公约数?(如9 15 值是3) int GCD(int a,int b)
{
while(1)
{
if(a==b)
break;
if(a>b){
a=a-b;
}else{
b=b-a;
}
}
return a;
}
Load/Store 指令
注:load/store架构规定,存储器之间不能直接拷贝,需通过寄存器做中转 (比如讲FLASH中的指令传入到内存中就必须使用CPU寄存器做中转)
ldr r0,[r1](load)//r0=*r1r1里存放的是地址,把该地址里存放的内容读入到r0中
//LDRB(byte)LDRH(half word)
ldr r0,[r1,#8]//r0=*(r1+8)存储器地址为r1+8的字数据读入寄存器0。
ldr pc,_irq// pc = *(_irq)将标号中的内容放入pc中
str r0,[r1] (store)// *r1 = r0将寄存器r0中值写入到存储器地址为r1的空间中
str r0,[r1],#4// r0=*r1, r1=r1+4将r0 中的字数据写入以r1为地址的内存中,并将新地址r1+4 写入r1
str r0,[r1,#4]//*(r1+4)=r0将r0 中的字数据写入以r1+4 为地址的内存中
Pre or Post Indexed 寻址
Pre-indexed: STR r0,[r1,#12]
文章图片
例:
拷贝srcBuf里内容 到destBuf中:
.text
ldrr0,=srcBuf
ldrbr1,[r0]
ldrr0,=destBuf
strbr1,[r0]
srcBuf:
.byte0x01,02,0x03,0x04
.data
destBuf:
.space 8
.end
测验
用汇编实现下面功能 :
main()
{
int i=0;
constchar buf[]={1,2,3};
char destBuf[8];
for(i=0,i<3,i++)
{
destBuf[i] = buf[i];
}
}
GNU 汇编伪指令
.text将定义符开始的代码编译到代码段
.data将定义符开始的代码编译到数据段
.end文件结束
.equGPG3CON, 0XE03001C0 定义宏(即用GPG3CON代替 0XE03001C0)
.byte定义变量 1字节
.byte0x11,'a',0 定义字节数组
.word定义word变量 (4字节32位机)
.word 0x12344578,0x33445566
.string定义字符串.string"abcd\0"
ldr r0,=0xE0028008载入大常数0xE0028008 到r0中
.global_start声明_start 为全局符号
例拷贝ROM中字符串到RAM中:
.text
start:
ldrr5,=srcBuf
ldrr6,=destBuf
loop:
ldrb r4,[r5]
cmpr4,#0
beqmain_end
ldrbr0,[r5],#1
strbr0,[r6],#1
bloop
main_end:
【物联网之ARM体系结构及接口技术二(ARM指令)】bmain_end
srcBuf:
.string"abcdefg\0"
.data
destBuf:
.space8
.end
批量操作指令
? 批量操作指令(ia-Increment Afterib-Increment Beforeda-Dec After db-Dec Before)
ldmiar0!, {r3 - r10}//r0里地址指向的内容批量,load 到r3~r10寄存器中, r0里地址会自动加4
stmiar0!, {r3 - r10}//把r3~r10寄存器中内容,store 到r0里地址执行空间中,r0里地址会自动加4
? 例:实现块数据批量拷贝
r12指向源数据起始地址
r14指向源数据尾地址
r13指向目的数据起始地址
文章图片
例批量拷贝数据:
.text
ldr r12,=srcBuf
ldr r13,=dstBuf
ldmiar12!,{r0 - r11}
stmiar13!,{r0 - r11}
.data
srcBuf:
.string "abdfasdf13535dfksjdlfkjlksldkjflkl\0"
srcBuf_end:
dstBuf:
.space12*4
.end
堆栈操作指令
stmfd sp!,{r0-r12,lr}将寄存器r0~r12 lr中的值存入栈中
常用于中断保护现场,! 表示会自动偏移
ldmfd sp!,{r0-r12,pc}^将栈中值逐个弹出到寄存器r0~r12 pc中
常用于中恢复断现场,^表示会恢复spsr到cpsr
文章图片
ARM 指令 高级
? 软中断指令
swi 0x02产生软中断, 软中断号为2
文章图片
推荐阅读
- PMSJ寻平面设计师之现代(Hyundai)
- 太平之莲
- 跌跌撞撞奔向你|跌跌撞撞奔向你 第四章(你补英语,我补物理)
- 闲杂“细雨”
- 七年之痒之后
- 深入理解Go之generate
- 由浅入深理解AOP
- 做一件事情的基本原理是什么()
- 基于微信小程序带后端ssm接口小区物业管理平台设计
- 期刊|期刊 | 国内核心期刊之(北大核心)