ARM指令集——条件执行、内存操作指令、跳转指令
ARM 汇编指令条件执行
在ARM模式下,任何一条数据处理指令可以选择是否根据操作的结果来更新CPSR寄存器中的ALU状态标志位。在数据处理指令中使用S后缀来实现该功能。
不要在CMP,CMN,TST或者TEQ指令中使用S后缀。这些比较指令总是会更新标志位。
在Thumb模式下,所有数据处理指令都更新CPSR中的标志位。有一个例外就是:当一个或更多个高寄存器被用在MOV和ADD指令时,此时MOV和ADD不能更新状态标志.
几乎所有的ARM指令都可以根据CPSR中的ALU状态标志位来条件执行。参见表2-1条件执行后缀表。
在ARM模式下,你可以:
- 根据数据操作的结果更新CPSR中的ALU状态标志;
- 执行其他几种操作,但不更新状态标志;
- 根据当前状态标志,决定是否执行接下来的指令。
在Thumb模式,大多数操作总是更新状态标志位,并且只能使用条件转移指令(B)来实现条件执行。该指令(B)的后缀和在ARM模式下是一样的。其他指令不能使用条件执行。
ALU状态标志
CPSR寄存器包含下面的ALU状态标志:
N | Set when the result of the operation was Negative |
Z | Set when the result of the operation was Zero |
C | Set when the operation result in a Carry(发生进位,或借位) |
V | Set when the operation caused oVerflow(操作造成溢出) |
Q | ARM architecture v5E only sticky flag |
2.5.2 执行条件
N,Z,C,V相关的条件码后缀如下表所列:
示例1
ADD r0, r1, r2 ; r0 = r1 + r2, 不更新标志位
ADDS r0, r1, r2 ; r0 = r1 + r2, 后缀S表示更新标志位
ADCSS r0, r1, r2 ; If C 标志为1,则执行r0 = r1 + r2, 且更新标志,
CMP r0, r1 ; CMP指令肯定会更新标志.
示例2 求最大公约数
gcd
CMP r0, r1
BEQ end ; r0 = r0 结束程序
BLT less ; r0 < r1 跳转至 less
SUB r0, r0, r1 ; r0 > r1时 r0 = r0 - r1
B gcd ; 条件都不满足是继续循环
less
SUB r1, r1, r0 ; r0 < r1 r1 = r1 - r0
B gcd
end
示例3
MAIN
mov r1, #
mov r2, #
cmp r1, r2
beq FUNC ;if(eq) b FUNC => 实质:if(z == 1) b FUNC
bne FUNC ;实质:if(z == 0) b FUNC
mov r3, #
mov r4, #
FUNC
mov r5, #
mov r6, #
寻址方式
基地址变址寻址方式
种类 | 格式 | 模式 |
1 | [Rn, #±<offset_12]> | 立即数前索引寻址 |
2 | [Rn, ±Rm] | 寄存器前索引寻址 |
3 | [Rn, Rm, <shift>#<offset_12>] | 寄存器位移的前索引寻址 |
4 | [Rn, #±<offset_12>]! | 立即数自动索引寻址 |
5 | [Rn, ±Rm]! | 寄存器自动索引寻址 |
6 | [Rn, Rm, <shift<#<offset_12>]! | 寄存器移位的自动索引寻址 |
7 | [Rn], #±<offset_12> | 立即数后索引寻址 |
8 | [Rn], ±<Rm> | 寄存器后索引寻址 |
9 | [Rn], ±<Rm>, <shift>#<offset_12> | 带移位的寄存器后索引寻址 |
寄存器前索引寻址
mov r0, #0x40000000
mov r1, #0xF000000F
str r1, [r0, #] ;将 r1 中的数据存储到地址为 r0 + 4 的内存空间中
寄存器移位的前索引寻址
mov r2, #
str r1, [r0, r2, lsl #] ;将 r1 中的数据存储到地址为 r0 + (r2 << 1)的内存空间中
寄存器后索引寻址
str r1, [r0], # ;将 r1 中的数据存储到地址为 r0 的内存空间中,然后 r0 = r0 + 4
寄存器自动索引寻址
str r1, [r0, #]! ;将 r1 中的数据存储到 r0 + 4 的内存空间中, 然后 r0 = r0 + 4
多寄存器寻址/块拷贝寻址 LDM STM
对栈进行操作是,使用较多 比如说 用 IA 自动索引寻址存,就用 DB 自动索引读
Load/Store指令
Load/store是一组内存访问指令,用来在ARM寄存器和内存之间进行数据传送,ARM指令中有3种基本的数据传送指令。
- 单寄存器 Load/Store 内存访问指令(single register):这些指令为ARM寄存器和存储器提供了更灵活的单数据项传送方式。数据可以使字节,16位半字或32位字
- 多寄存器 Load/Store 内存访问指令:可以实现大量数据的同时传送,主要用于进程的进入和退出、保存和恢复工作寄存器以及复制寄存器中的一片(一块)数据
- 但寄存器交换指令(single register swap): 实现寄存器数据和内存数据进行交换,而且是在一条指令中完成,执行过程中不会受到中断干扰
单寄存器Load/Store指令
LDR指令:用于从内存中将一个32位的字读取到目标寄存器 指令格式 LDR{<cond>} <Rd>, <addr_mode>
;指令举例
LDR R1, [R0, #0x12] ;将R0 + 12地址处的数据读出,保存到R1中(R0保持不变)
LDR Rd,[Rn], #0x04 ;立即数后索引寻址,Rn的值用作传输数据的存储地址。在数据传送后,将偏移量 0x04 与Rn相加,记过写回到 Rd中
STR指令:用于将一个32位的字节数据写入到指令中指定的内存单元 指令格式 STR{<cond>} <Rd>,<addr_mode>
;LOAD/STORE指令
;向内存写入数据 STR
mov r0, #
mov r1, #ff000000
str r1, [r0] ;用于将一个32位的字数据写入到指令指定的内存单元(以 r0 值为起始地址的 4byte 内存单元)
strb r1, [r0] ;将r1 中的 [7:0]存储到 r0 对应的内存空间
strh r1, [r0] ;将r1 中的 [15:0]存储到 r0 为起始地址的两个字节的内存空间
;在对数据进行操作时,应根据数据本身的属性(几个字节)进行操作
多寄存器Load/Store指令
LDM指令:实现数据从连续的内存单元中读取到指令指定的寄存器列表中。值得注意的是 LDM指令和STM指令:序号的寄存器对应内存中高地址的数据
指令格式: LDM{<cond>}<addressing_mode> <Rn>{!}, <registers>
STM指令:实现将指令中寄存器列表里的数值写入到一块连续的内存单元之中
指令格式: STM{<cond>} <addressing_mode> <Rn>{!}, <register>
LDM/STM <cond>的几种寻址方式:
格 式 | 地址变化格式 | ||
1 | IA(Increment After) | 后递增方式 | 先存储后增长 |
2 | IB(Increment Before) | 先递增方式 | 现增长后存储 |
3 | DA(Decrement After) | 后递减方式 | 先存储后递减 |
4 | DB(Decrement Before) | 先递减方式 | 先递减后存储 |
mov r0, #0x40000000
mov r1, #
mov r2, #
mov r3, #
ldm r0, {r1-r3}
stm r0, {r1-r3} ;将 r1 - r3 寄存器(连续寄存器)中的数据存储到 以 r0 位起始地址的内存空间中
stm r0, {r3, r1} ;将 r1 、 r3 寄存器(不连续寄存器)中的数据存储到 以 r0 位起始地址的内存空间中
;批量操作时,低编号的寄存器数据对应内存中的低地址
stm r0!, {r1-r3} ;寄存器批量存储,也适用自动索引寻址, 操作完成后 r0 = r0 + (寄存器个数)*4
跳转指令
B和BL跳转指令
MAIN
mov r0, #
mov r1, #
mov lr, pc ;B 指令不会自动保存 PC;手动保存返回地址、当前PC
b lable ;跳转到标号 FUNC (标号的实质是地址)
mov r3, r0
FUNC
sub r0, r1, r0
mov pc,lr ;返回主程序继续执行
跳转指令是改变指令执行顺序的标准方式 (控制流指令)
B 和 BL 指令都是 相对跳转(短跳转) 指令,通过偏移量跳转, 最大跳转距离是 ±32M
使用 mov pc, <>可以实现 对跳转(长跳转)(不会保存当前 PC 值)
关于B指令和BL指令最大跳转距离是 ±32M:
ARM汇编每条指令占用 4byte,生成机器码 B 、BL存放在bits[31:24], bits[23:0]是立即数空间,可以表示 2^24个地址。由于每条汇编指令占用4byte字节(最低两位都为 0),因此可以使用 24位二进制数来表示 26 位的寻址空间。
B指令和BL指令的区别:
- B指令在使用时不会对当前 PC 值进行保存,为保证跳转指令执行后能正常返回,要手动对其进行保存
- BL (带连接的跳转指令)能够在跳转时对当前 PC 值自动进行保存。
带状态切换的跳转指令 BX
不会保存跳转前 PC 值 ±32M范围
带状态切换(ARM&Thmub)的跳转指令BX ,语法格式:BX{<cond>} <Rm> ,使程序跳转到指令中参数 Rm 指定的地址进行执行。并将 Rm 的第 0 位复制到 CPRS 中的 T 位, bit[31: 1]存入PC。
PC也可以作为 Rm 寄存器使用,当PC作为 Rm 使用时,指令 BX PC 便跳转到当前指令下面第 2 条指令出执行(三级流水线:当前正在执行的指令地址为 PC - 8,正在译码的指令为 PC - 4, 正在取指的指令是 PC)。但这种方式不值得推荐,最好使用下面的方式完成这种跳转。
mov pc, pc
;或者
add pc, pc, #
带状态切换的连接跳转指令
与BX功能一致,但会自动保存跳转时的 PC 值,语法格式: BLX <target_add> 。target_add为指令的跳转目标地址,该地址是一个立即数
状态(寄存器)操作指令
ARM指令集提供了两条指令(MSR,MRS),用来操作状态寄存器PSR
MRS指令,语法格式 MRS {cond} Rd, PSR 用于把CPSR或SPSR的值传送到一个寄存器;
MSR指令,语法格式 MSR {cond} PSR_filed, #immed_8r 或 MSR {cond} PSR_filed, Rm 用于把一个寄存器的值或一个立即数传送到CPSR或SPSR;使用这两条只能可以实现对程序状态寄存器的状态修改操作。
在使用MSR指令对PSR进行修改操作时,要通过field设置状态寄存器需要操作的域。状态寄存器的32位被分为4个8位的域(filed)分别为:bits[31:24]条件域,用 F 表示; bits[23: 16]状态域,用 S 表示;bits[15:8]预留域,用 X 表示;bits[7:0]控制域,用 C 表示。
;程序举例:是能IRQ中断
ENABLE_IRQ
MRS R0,CPSR
BIC R0,R0,# ;将CPSR bit7 I 清零,是能IRQ
MSR CPSR_c,R0 ;典型的读-改-回写操作
MOV PC,LR
异常产生指令
ARM指令集提供了两条产生异常的指令(中断指令 SWI,断点中断指令 BKPT),通过这两条指令可以用软件的方法实现异常。
中断指令
软件中断指令 SWI (software Interrupt)用于产生软中断,实现从用户模式切换到管理模式,CPSR保存到管理模式的 SPSR 中,执行转移到 SWI 向量。
语法格式 SWI {<cond>} <immed_24> immed_24 为中断号
栈
栈:按增长方向分为 递增栈;递减栈
按压栈操作顺序(sp位置)分为;满栈和空栈
满栈(FULL):sp指向栈顶元素
空栈(EMPTY):sp指向栈顶元素相邻位置
根据栈的不同分类,将其寻址方式分为以下4种
1)满递减 FD(Full Descending)
2)空递减 ED(Empty Descending)
3)满递增 FA(Full Asceding)
4)空递增 EA(Empty Ascending)
习惯上大都使用满减栈。
压栈出栈的几种操作方式
;初始化栈
mov sp, #0x40000018
MAIN
mov r0, #
mov r1, #
bl FUNC
add r2, r0, r1
FUNC
;压栈保护现场
stmfd sp!, {r0, r1}
mov r0, #
mov r1, #
sub r2, r1, r0
;出栈恢复现场
ldmfd sp!, {r0, r1}
mov pc, lr ;初始化栈
MAIN
mov r0, #
mov r1, #
bl FUNC
add r2, r0, r1
FUNC
;压栈保护现场
stmfd sp!, {r0, r1, lr}
mov r0, #
mov r1, #
sub r2, r1, r0
;出栈恢复现场
ldmfd sp!, {r0, r1, pc}
swp r0, r1, [r2]
;将r0中的数据放入内存地址是r2的地址空间,同时将r2中的值放入r1寄存器
;处理器与内存之间进行数据交换 交换过程不会被打断
ARM指令集——条件执行、内存操作指令、跳转指令的更多相关文章
- ARM指令集——数据处理指令
ARM汇编指令集 ARM汇编文件的组成 指令:编译完成后作为一条指令(机器码)存储在内存单元中,CPU执行时能够完成处理的操作 伪指令:在编译时替换成能被识别的ARM指令 伪操作:知道编译器进行编译, ...
- ARM指令集----杂项指令
ARM指令集可以分为6类,即是跳转指令,数据处理指令,程序状态传输指令,Load.Store指令,协处理器指令和异常中断指令 跳转指令: 在ARM中有两种方式可以实现程序的跳转,一种是跳转指令,另一种 ...
- 常用 ARM 指令集及汇编
ARM7TDMI(-S)指令集及汇编 ARM 处理器是基于精简指令集计算机(RISC)原理设计的,指令集和相关译码机制 较为简单,ARM7TDMI(-S)具有 32 位 ARM 指令集和 16 位 T ...
- 13 ARM指令集与Thumb指令集
指令格式 ARM基本格式 <opcode>{<cond>}{S}{.W|.N}<Rd>,<Rn>{,<operand2>} opecode: ...
- 【嵌入式开发】裸机引导操作系统和ARM 内存操作 ( DRAM SRAM 类型 简介 | Logical Bank | 内存地址空间介绍 | 内存芯片连接方式 | 内存初始化 | 汇编代码示例 )
[嵌入式开发]ARM 内存操作 ( DRAM SRAM 类型 简介 | Logical Bank | 内存地址空间介绍 | 内存芯片连接方式 | 内存初始化 | 汇编代码示例 ) 一. 内存 ...
- ARM学习笔记2——分支跳转指令
一.Arm指令条件码和条件助记符 二.跳转指令B 1.作用 跳转指令B使程序跳转到指定的地址执行程序(跳转范围是PC-32MB到PC+32MB) 2.指令格式(注:B后面如果有条件,条件就是紧跟在B后 ...
- 汇编 sub减法指令 比较指令CMP JZ条件跳转指令
二.SUB指令 减法指令SUB (SUBtract) 格式: SUB A,B //A=A-B; 功能: 两个操作数的相减,即从A中减去B,其结果放在A中. 二.CMP 和JZ 指令 比较指令CMP 格 ...
- ARM指令集—SWP指令
ARM指令集-SWP指令 SWP和SWPB是ARM指令集中对存储单元的原子操作.即对存储单元的一次读和一次不可被切割. SWP和SWPB分别完毕存储器和寄存器之间 一个字(32bit)和一个字节(8b ...
- arm学习之汇编跳转指令总结
目前所知道的跳转指令有 b,bl,bep,bne.他们共同点是都是以b开头,首先从字面上分析:b:是Branch,表示分支.bl:是Branch Link表示带连接的分支.bep:Branch ,Eq ...
随机推荐
- Window 10通过网线和Wifi连接树莓派
几个月前买了个树莓派,扔在一边没有捣鼓,今天搞定了笔记本通过家里的wifi登录树莓派,下面列出设置过程. 实验环境: 网络:只有wifi 材料:笔记本一台(Win10),树莓派一台,EDUP USB无 ...
- i2c sub system __i2c_board_list/klist_devices/klist_drivers
i2c_devinfo全局链表: __i2c_board_list 用来挂接 i2c_board_info,这个信息用来生成 i2c_client i2c_client 链表: i2c_bus_typ ...
- 什么是工程师文化?各位工程师是为什么活的?作为一个IT或互联网公司为什么要工程师文化?
为什么要工程师文化? 看看最近二十年来社会的发展,计算机和互联网已经渗透到了这个社会的每一个角落,各式各样的计算机技术成为了整个世界发展的强大引擎,各式各样的创新,无论是业务创新还是技术创新,都是依托 ...
- DNN7网站系统需求及部署指南详解
此安装指南适用于DNN6.x和DNN7.x在本地测试及主机的安装.最近QQ群里不少朋友问我关于DotNetNuke的安装和运行的问题. 为了让大家更清楚地了解DNN的安装方式,我在这里对DotNetN ...
- hadoop文本转换为序列文件
在以前使用hadoop的时候因为mahout里面很多都要求输入文件时序列文件,所以涉及到把文本文件转换为序列文件或者序列文件转为文本文件(因为当时要分析mahout的源码,所以就要看到它的输入文件是什 ...
- 4月13日 php
用php打印乘法表: <html> <head> <title>我的第一个PHP页面</title> </head> <body> ...
- 百度PHP实习一面面试题-算法-二维有序矩阵的查找
题目描述 有一个二维矩阵,每一行的元素,从左到右保持严格递增,每一列的元素,从上到下保持严格递增.查找给定元素elem,返回NULL或元素位置. 1 3 7 15 16 2 5 8 17 19 3 6 ...
- php 函数strtr 替换函数实例解析 strtr 速度比较快
先来看看这个php字符串替换函数 PHP字符串替换函数strtr()的两种状态 strtr(string,from,to) 或者strtr(string,array) 首先针对PHP字符串替换函数st ...
- ADT-位图
利用位图数据结构实现排序,利用每一位的下标作为索引,每位的值作为属性值,可以表示存在或不存在,适合存储稠密的数据,排序遍历的范围会是索引的最大值 最后发现耗时比python中list自带的sort多, ...
- Greatest common divisor(gcd)
欧几里得算法求最大公约数 If A = 0 then GCD(A,B)=B, since the GCD(0,B)=B, and we can stop. If B = 0 then GCD(A,B) ...