博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ARM基础
阅读量:4631 次
发布时间:2019-06-09

本文共 3049 字,大约阅读时间需要 10 分钟。

ARM汇编:(APCS过程调用标准)

  汇编:用助记符(如$ # .)代替操作码,用地址符号或标签代替地址码的编程语言

特点:

   优点:可以直接访问硬件,目标代码简短,执行速度快(CPU启动时需要直接操作,所以用汇编)

   缺点:可移植性差,可阅读性差(不同平台指令有差别)

ARM指令集特点

     1 指令码长度固定,如32bit

   2 几乎所有指令都是有条件执行

   3 寄存器与内存之间交换数据采用专用指令集

   CPU内部有很多通用寄存器,如R0-R15,R0-R12可以随便存储数据,寄存器中的数据主要是从外存取出来的,所以为了提高效率把寄存器和寄存器里面交互使用专用指令,寄存器与内存之间交互也使用另一种专用指令,这样就可以把他们分离开,让数据操作变的效率更高。

指令格式:

 

  opcode:指令助记符

  cond:执行条件

  s:是否影响CPSR寄存器的值

  Rd:目标寄存器

  Rn:第一个操作数的寄存器

  operand2:第二个操作数

 

指令编码格式:

 

32-28

27-25

24-21

20

19-16

15-12

11-0

cond

001

opcode

S

Rn

Rd

11-8(移位)

7-0(数据)

operand2

 

代码格式:

 

数据运算指令:

指令

功能

实例

注释

mov

给一个寄存器赋值

mov r0,#10

r0=10

mov r0,r1

r0=r1

mvn

把一个数值按位取反后赋值给一个寄存器

mvn r0,#0xff

r0=~0xff

mvn r0,r1

r0=~r1

add

计算两个数值的加法

add r0,r0,#10

r0=r0+10

add r0,r0,r1

r0=r0+r1

sub

计算两个数值的减法

sub r0,r0,#10

r0=r0-10

sub r0,r0,r1

r0=r0-r1

mul

乘法

mul r0,r1,r2

r0=r1*r2

cmp

比较

cmp r0,r1

r0-r1影响CPSR标志位

cmp r0,#10

r0-10影响CPSR标志位

 

  ldr r5,=20008000  ;20008000不是立即数,而是将它赋值为r5,此条指令是伪指令:伪指令在编译器编译的时候把伪指令分解为几条指令实现;

往寄存器中存放数据有三种方式:

  1 mov 有效立即数

  2 mvn 立即数按位取反的数

  3 ldr 任何数

数据运算指令:

指令

功能

实例

注释

orr

按位或

orr r0,r0,r1

r0=r0|r1

orr r0,r0,#10

r0=r0|10

and

按位与

and r0,r0,r1

r0=r0&r1

and r0,r0,#10

r0=r0&10

bic

位取反

bic r0,r0,r1

r0=r0&(~r1)

bic r0,r0,#10

r0=r0&(~10)

 

内存操作指令

指令

功能

实例

注释

swp Rd,Rm,[Rn]

将寄存器中的值与内存地址中的值交换

注:Rn不能与Rd和Rm相同

swp r0,r1,[r2]

r0=*r2

*r2=r1

ldr

把数据从内存加载到寄存器

ldr r0,=addr

r0=addr

ldr r1,[r0]

r1=*r0

ldr r1,[r0,#4]

r1=*(r0+4)

ldr r1,[r0,#4]!

r1=*(r0+4);r0+=4

ldr r1,[r0],#4

r1=*r0;r0+=4

str

把数据从寄存器保存到内存

str r1,[r0]

*r0=r1

str r1,[r0,#4]

*(r0+4)=r1

str r1,[r0,#4]!

*(r0+4)=r1;r0+=4

str r1,[r0],#4

*r0=r1;r0+=4

 

    str r1,[r0] 把r1存储到r0指向的内存地址(r0指向的地址是0x40000000)

    ldr r1,[r0] 把r0指向的内存地址中的数据存储到r1寄存器中

/******************r1、r2、r3、r4四个数据存储到0x20000000为首的地址空间*****************/  mov r0,#0x20000000  mov r1,#0x11  mov r2,#0x22  mov r3,#0x33  mov r4,#0x44  str r1,[r0]  add r0,r0,#4  str r2,[r0]  add r0,r0,#4  str r3,[r0]  add r0,r0,#4  str r4,[r0]  add r0,r0,#4

内存连续操作指令

指令

功能

实例

ldmfd

把数据从内存加载到寄存器

ldmfd sp!,{r0-r12,lr}

stmfd

把数据从寄存器保存到内存

stmfd sp!,{r0-r12,lr}

 

ldr r0,=0x20000100mov r1,#0x11mov r2,#0x22mov r3,#0x33mov r4,#0x44stmfd r0! ,{r1-r4} ;r0向下存储,先减4,在存储ldmfd r0! ,{r5-r8} ;r0向上读取,先读取,再加4 

实际中什么时候用到连续的存储数据或者读取数据?

  在函数发生跳转或标签发生跳转的时候,我们需要保存现场和恢复现场。

  CPU当前工作在一种模式下,比如SVC管理模式下,管理模式操作寄存器只有这么多,当发生函数跳转的时候,当前函数肯定有一些变量存到寄存器。跳转到另一个函数也有一些变量要存到寄存器,有可能冲突。所以需要保存现场

  保存现场:保存到内存中stmfd

  恢复现场:从内存恢复到寄存器ldmfd

保存现场

apcs规定r13(sp):指向内存地址

ldr sp,=0x20000100

mov r1,#0x11

mov r2,#0x22

stmfd sp! ,{r0-r12,r14}  ;已经保存现场可以跳转到其他函数

ldmfd sp!,{r0-r12,r14};恢复现场

;可以跳转到其他函数

;函数不管跳转几次,始终要保证跳转之前和执行完毕,sp保持不变

跳转指令

指令

功能

实例

注释

b

跳转

b lable

跳转lable处执行

bl

跳转并保存返回地址

bl lable

保存下一条指令的地址到lr,并跳转到lable处执行

 

  mov r0.#0x01

  mov lr,pc  ;lr专门用于备份pc,保存下一条指令(保存了mov r2,#0x02的地址)

b func1  ;如果没有mov lr,pc和mov pc,lr 函数就不会运行mov r2,#0x02

  mov r2,#0x02

func1

  mov r1,#0x03

  mov pc,lr ;手动修改pc内容,函数返回返回

程序运行到mov lr,pc时,pc指针已经指向了mov r2,#0x02

mov lr,pc

b func1

这两天语句可以写为:bl funcl

注:b,bl都是相对跳转,通过偏移量跳转,最大跳转距离是±32MB,实现长跳转可以通过修改pc实现(绝对跳转)

;mov pc,#0x10  ;0x10代表func1所在地址

ldr pc,=0x10

 

总结:

1 b bl(相对跳转)短跳转

2 mov ldr修改pc实现长跳转(绝对跳转)

3 b mov ldr都不会保存返回地址,bl会保存返回地址

转载于:https://www.cnblogs.com/dongry/p/10266198.html

你可能感兴趣的文章
poj3225 Help with Intervals
查看>>
wamp 配置多站点访问
查看>>
串级调节系统参数整定方法(串级调节器参数整定)
查看>>
Maven下载失败后lastUpdate文件删除
查看>>
CSS响应式:根据分辨率加载不同CSS的几个方法,亲测可用
查看>>
Java核心技术及面试指南 JDBC部分的面试题总结以及答案
查看>>
[转CSDN]android 滑动入门代码...[geoway]
查看>>
DayDream, 移动VR 2.0里程碑: 概述(上篇)
查看>>
数据产品经理工作(总结篇)
查看>>
算法导论 6-2 代码实现 C++
查看>>
Floyd-傻子也能看懂的弗洛伊德算法(转)
查看>>
python3 常见错误(一)
查看>>
php中怎么实现后台执行?
查看>>
jar包读取jar包内部和外部的配置文件,springboot读取外部配置文件的方法
查看>>
敏捷开发方法综述
查看>>
C语言中库函数strstr的实现
查看>>
python-希尔排序
查看>>
Vue中ref的使用要点
查看>>
python 日志
查看>>
Qt 学习之路 2(84):Repeater
查看>>