历史上的今天
返回首页

历史上的今天

今天是:2025年02月22日(星期六)

2020年02月22日 | ARM指令集——条件执行、内存操作指令、跳转指令

2020-02-22 来源:eefocus

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, #1

  mov r2, #1

  cmp r1, r2

  beq FUNC      ;if(eq) b FUNC => 实质:if(z == 1) b FUNC

  bne FUNC    ;实质:if(z == 0) b FUNC

  mov r3, #3

  mov r4, #4

FUNC

  mov r5, #5

  mov r6, #6


寻址方式 


基地址变址寻址方式 


种类 格式 模式

1 [Rn, #± 立即数前索引寻址

2 [Rn, ±Rm] 寄存器前索引寻址

3 [Rn, Rm, #] 寄存器位移的前索引寻址

4 [Rn, #±]! 立即数自动索引寻址

5 [Rn, ±Rm]! 寄存器自动索引寻址

6 [Rn, Rm, ]! 寄存器移位的自动索引寻址

7 [Rn], #± 立即数后索引寻址

8 [Rn], ± 寄存器后索引寻址

9 [Rn], ±, # 带移位的寄存器后索引寻址

 

寄存器前索引寻址


  mov r0, #0x40000000

  mov r1, #0xF000000F

  str r1, [r0, #4]  ;将 r1 中的数据存储到地址为 r0 + 4 的内存空间中


寄存器移位的前索引寻址


  mov r2, #8

  str r1, [r0, r2, lsl #1]  ;将 r1 中的数据存储到地址为 r0 + (r2 << 1)的内存空间中


寄存器后索引寻址


  str r1, [r0], #4  ;将 r1 中的数据存储到地址为 r0 的内存空间中,然后 r0 = r0 + 4


寄存器自动索引寻址 


str r1, [r0, #4]!  ;将 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{} ,  


;指令举例

  LDR R1, [R0, #0x12]  ;将R0 + 12地址处的数据读出,保存到R1中(R0保持不变)

  LDR Rd,[Rn], #0x04    ;立即数后索引寻址,Rn的值用作传输数据的存储地址。在数据传送后,将偏移量 0x04 与Rn相加,记过写回到 Rd中

 STR指令:用于将一个32位的字节数据写入到指令中指定的内存单元  指令格式  STR{} , 


;LOAD/STORE指令

;向内存写入数据 STR

mov r0, #40000000

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{} {!},  


STM指令:实现将指令中寄存器列表里的数值写入到一块连续的内存单元之中


指令格式: STM{} {!},  


LDM/STM 的几种寻址方式:


  格  式 地址变化格式  

1 IA(Increment After) 后递增方式 先存储后增长

2 IB(Increment Before) 先递增方式 现增长后存储

3 DA(Decrement After) 后递减方式 先存储后递减

4 DB(Decrement Before) 先递减方式 先递减后存储

   


mov r0, #0x40000000

  mov r1, #1

  mov r2, #2

  mov r3, #3

  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, #2

  mov r1, #3

  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{} ,使程序跳转到指令中参数 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, #0

 

带状态切换的连接跳转指令


 与BX功能一致,但会自动保存跳转时的 PC 值,语法格式: BLX 。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,#080  ;将CPSR bit7 I 清零,是能IRQ

  MSR  CPSR_c,R0  ;典型的读-改-回写操作

  MOV   PC,LR


异常产生指令


ARM指令集提供了两条产生异常的指令(中断指令 SWI,断点中断指令 BKPT),通过这两条指令可以用软件的方法实现异常。 


中断指令


软件中断指令 SWI (software Interrupt)用于产生软中断,实现从用户模式切换到管理模式,CPSR保存到管理模式的 SPSR 中,执行转移到 SWI 向量。


语法格式 SWI {}   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, #1

  mov r1, #1

  bl FUNC          

  add r2, r0, r1

FUNC

  ;压栈保护现场

  stmfd sp!, {r0, r1}

  mov r0, #2

  mov r1, #4

  sub r2, r1, r0

  ;出栈恢复现场

  ldmfd sp!, {r0, r1}

  mov pc, lr   


;初始化栈 

MAIN

  mov r0, #1

  mov r1, #1

  bl FUNC          

  add r2, r0, r1

FUNC

  ;压栈保护现场

  stmfd sp!, {r0, r1, lr}

  mov r0, #2

  mov r1, #4

  sub r2, r1, r0

  ;出栈恢复现场

  ldmfd sp!, {r0, r1, pc}   


swp r0, r1, [r2]

 ;将r0中的数据放入内存地址是r2的地址空间,同时将r2中的值放入r1寄存器

 ;处理器与内存之间进行数据交换  交换过程不会被打断

推荐阅读

史海拾趣

台湾致强(FORT)公司的发展小趣事

随着产品技术的不断成熟,致强科技开始积极寻求市场拓展。2016年,致强科技携手上海晟霆电子科技有限公司,共同致力于致强品牌合金电阻在中国内地市场的推广与销售。这一合作不仅扩大了致强产品的市场覆盖范围,还通过本地化服务提升了客户满意度。通过精准的市场定位和高效的营销策略,致强电阻迅速在内地市场占据了一席之地,成为众多电子企业信赖的合作伙伴。

Foxconn_Optical_Interconnect_Technologies__Inc.公司的发展小趣事

在追求企业发展的同时,致强科技始终不忘对环境的责任。公司积极响应环保法规要求,将环保理念融入产品研发、生产和销售的各个环节。通过采用环保材料、优化生产流程、实施节能减排等措施,致强科技有效降低了产品对环境的负面影响。此外,公司还定期评估并符合最新的环保法规要求,确保企业与消费者的价值观和环境保护目标相一致。

Electronic-Bauteile Goerlitz GmbH公司的发展小趣事

Electronic-Bauteile Goerlitz GmbH公司自创立之初,就以其独特的技术创新为核心竞争力。公司不断投入研发资源,开发出了一系列具有竞争力的电子产品部件。这些部件以其高性能、低功耗和可靠性,赢得了市场的广泛认可。公司通过与高校和研究机构的合作,不断引进新技术,推动产品升级换代,确保了其在行业中的领先地位。

Efficient Power Conversion公司的发展小趣事

随着EPC公司在氮化镓技术领域的领先地位日益稳固,一些竞争对手开始试图通过不正当手段获取其技术。为了维护自身的合法权益,EPC公司积极寻求法律途径来保护其专利。2023年,EPC公司向美国联邦法院和美国国际贸易委员会提起诉讼,指控英诺赛科(珠海)科技有限公司及其子公司侵犯了其基础专利组合中的四项专利。这一诉讼引起了行业的广泛关注,也再次证明了EPC公司对专利保护的重视。

DETCO公司的发展小趣事

当5G技术开始在全球范围内推广时,ElectronicsCorp看到了巨大的商机。公司迅速调整战略,将重点转向5G相关产品的研发。通过与全球领先的通信公司合作,ElectronicsCorp推出了一系列5G手机和通信设备。这些产品不仅性能卓越,而且价格合理,赢得了消费者的青睐。随着5G技术的普及,ElectronicsCorp的市场份额不断扩大。

全智景(Allvision)公司的发展小趣事

在电子行业快速发展的背景下,全智景公司始终保持着强烈的创新意识和敏锐的市场洞察力。公司不断推出具有创新性的产品和服务,如智能安防监控系统、无人机视觉导航系统等,满足了市场不断变化的需求。同时,全智景公司还积极投入研发资源,探索新兴技术的应用前景,为公司的未来发展储备了更多的技术储备。

问答坊 | AI 解惑

有利用单片机实现数据采集之后再串口传输的实例吗?

因为接触单片机应用的时间不常,想看看有没有这方面的实例可以参考的 谢谢啦!!…

查看全部问答>

VS.NET 2005开发PDA用程序

有这么一个小程序,就是当数据库有数据的时候,会弹出一个对话框,在弹出对话框的同时,我想加上一段提示音,但是试了好几种方法,都不行,哪位高手能指教下啊,小弟感激不敬!!…

查看全部问答>

哪位在本本上用并口连接过H-Jtag 调试?

这样的是: 在PC上我跑IAR, 和 ADS 的两个工程文件,都没有问题, 用自己做的调试板+H-JTAG,都能正常 而换到本本上,在H-JTAG时,检测硬件都没问题,但调试时,分别出了问题: 1 在ADS 上, 按F5后,跑不到,MAIN() 函数那,发现死在 PLL初 ...…

查看全部问答>

WINCE驱动程序是否可以同时开启SPI中断和DMA中断?

请教一下,一个驱动程序程序中,可不可以同时存在SPI中断和DMA中断?还是只能用一个中断? 当驱动程序使用了DMA中断后,SPI中断是否起作用?…

查看全部问答>

【求助】关于延时的问题!

我用C写延时子程序,请问怎么样才可以算出延时了多久呀!好像430讲时序方面也讲的很少,哪位高手有这方面的资料或程序,可否借光参考一下。…

查看全部问答>

基于TMS320F28335的光伏并网模拟装置

基于TMS320F28335的光伏并网模拟装置…

查看全部问答>

0-10mv交流经过运放输出0-5v的直流

本帖最后由 dontium 于 2015-1-23 13:11 编辑 设计电路,在模电书上看到信号放大的电路,是三个运放,有没有两个运放的还有就是单电源运放放大的 …

查看全部问答>

TI M4处理器

以前主要搞PIC单片机软件,现在想学习TI  M4处理器 能给点的建议吗?(最好能推荐款开发板)。…

查看全部问答>

病人/老人身体状况监测系统

采用Ti SensorTag,安卓手机 , 能实时连续采集病人/老人的身体状况,比如体温脉搏,心率,皮肤电阻等信息,实实传到具有蓝牙设备的手持安卓终端上(手机),来进行监测,分析,并给病人/老人提醒,建议。危险或异常情况下可以通过监测端短信给监护 ...…

查看全部问答>