ARM 微处理器支持加载/存储指令用于在寄存器和内存之间传送数据,载入指令用于将内存中的数据传送到寄存器,存储指令则完成相反的操作。常用的加载存储指令如下:
LDR 字数据加载指令
LDRB 字节数据加载指令
LDRH 半字数据加载指令
STR 字数据存储指令
STRB 字节数据存储指令
STRH 半字数据存储指令
1. LDR 指令
LDR 指令的语法为:
LDR{条件} 目的寄存器,<内存地址>
LDR 指令用于从内存中将一个32 位的字数据传送到目的寄存器中。该指令通常用于从内存中读取32 位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC 作为目的寄存器时,指令从内存中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。该指令在程序设计中比较常用,且寻址方式灵活多样,请读者认真掌握。指令范例:
LDR R0,[R1] ;将内存地址为R1 的字数据读入寄存器R0。
LDR R0,[R1,R2] ;将内存地址为R1+R2 的字数据读入寄存器R0。
LDR R0,[R1,#8] ;将内存地址为R1+8 的字数据读入寄存器R0。
LDR R0,[R1,R2] ! ;将内存地址为R1+R2 的字数据读入寄存器R0,并将新地址R1+R2 写入R1。
LDR R0,[R1,#8] ! ;将内存地址为R1+8 的字数据读入寄存器R0,并将新地址R1+8 写入R1。
LDR R0,[R1],R2 ;将内存地址为R1 的字数据读入寄存器R0,并将新位址R1+R2 写入R1。
LDR R0,[R1,R2,LSL#2]! ;将内存地址为R1+R2×4 的字数据读入寄存器R0,并将新地址R1+R2×4 写入R1。
LDR R0,[R1],R2,LSL#2 ;将内存地址为R1 的字数据读入寄存器R0,并将新位址R1+R2×4 写入R1。
2. LDRB 指令
LDRB 指令的语法为:
LDR{条件}B 目的寄存器,<内存地址>
LDRB 指令用于从内存中将一个8 位的字节数据传送到目的寄存器中,同时将寄存器的高24 位清零。该指令通常用于从内存中读取8 位的位元组数据到通用寄存器,然后对数据进行处理。当程序计数器PC 作为目的寄存器时,指令从内存中读取的字数据被当作目的地址,从而可以实现程序流程的跳转。
指令范例:
LDRB R0,[R1] ;将内存地址为R1 的字节数据读入寄存器R0,并将R0的高24 位清零。
LDRB R0,[R1,#8] ;将内存地址为R1+8 的字节数据读入寄存器R0,并将R0 的高24 位清零。
3. LDRH 指令
LDRH 指令的语法为:
LDR{条件}H 目的寄存器,<内存地址>
LDRH 指令用于从内存中将一个16 位的半字数据传送到目的寄存器40
中,同时将寄存器的高16 位清零。该指令通常用于从内存中读取16 位的半字数据到通用寄存器,然后对数据进行处理。当程序计数器PC 作为目的寄存器时,指令从内存中读取的字数据被当作目的地址,从而可以实现程序流程的跳移。指令范例:
LDRH R0,[R1] ;将内存地址为R1 的半字数据读入寄存器R0,并将R0 的高16 位清零。
LDRH R0,[R1,#8] ;将内存地址为R1+8 的半字数据读入寄存器R0,并将R0的高16 位清零。
LDRH R0,[R1,R2] ;将内存地址为R1+R2 的半字数据读入寄存器R0,并将R0 的高16 位清零。
4. STR 指令
STR 指令的语法为:
STR{条件} 来源寄存器,<内存地址>
STR 指令用于从来源寄存器中将一个32 位的字数据传送到内存中。该指令在程序设计中比较常用,且寻址方式灵活多样,使用方式可参考指令LDR。指令范例:
STR R0,[R1],#8 ;将R0 中的字数据写入以R1 为地址的内存中,并将新地址R1+8 写入R1。
STR R0,[R1,#8] ;将R0 中的字数据写入以R1+8 为地址的内存中。
5. STRB 指令
STRB 指令的语法为:
STR{条件}B 来源寄存器,<内存地址>
STRB 指令用于从来源寄存器中将一个8 位的字节数据传送到内存中。该字节数据为来源寄存器中的低8 位。指令范例:
STRB R0,[R1] ;将寄存器R0 中的字节数据写入以R1 为地址的内存中。
STRB R0,[R1,#8] ;将寄存器R0 中的字节数据写入以R1+8 为地址的内存中。
6. STRH 指令
STRH 指令的语法为:
STR{条件}H 来源寄存器,<内存地址>
STRH 指令用于从来源寄存器中将一个16 位的半字数据传送到内存中。该半字数据为来源寄存器中的低16 位。指令范例:
STRH R0,[R1] ;将寄存器R0 中的半字数据写入以R1 为地址的内存中。
STRH R0,[R1,#8] ;将寄存器R0 中的半字数据写入以R1+8 为地址的内存中。
2.6.6连续数据加载/存储指令
ARM 微处理器所支持连续数据加载/存储指令可以一次在一片连续的记忆体单元和多个寄存器之间传送数据,连续加载指令用于将一片连续的内存中的数据传送到多个寄存器,连续数据存储指令则完成相反的操作。常用的载入存储指令如下:
LDM 连续数据加载指令
STM 连续数据存储指令
LDM(或STM)指令
LDM(或STM)指令的语法为:
LDM(或STM){条件}{类型} 基址寄存器{!},寄存器列表{∧}
LDM(或STM)指令用于从由基址寄存器所指示的一片连续内存到寄存器列表所指示的多个寄存器之间传送数据,该指令的常见用途是将多个寄存器的内容入堆栈或出堆栈。其中,{类型}为以下几种情况:
IA 每次传送后地址加1;
IB 每次传送前地址加1;
DA 每次传送后地址减1;
DB 每次传送前地址减1;
FD 满递减堆栈;
ED 空递减堆栈;42
FA 满递增堆栈;
EA 空递增堆栈;
{!}为可选后缀,若选用该后缀,则当数据传送完毕之后,将最后的地址写入基址寄存器,否则基址寄存器的内容不改变。基址寄存器不允许为R15,寄存器列表可以为R0∼R15 的任意组合。{∧}为可选后缀,当指令为LDM 且寄存器列表中包含R15,选用该后缀时表示:除了正常的数据传送之外,还将SPSR 复制到CPSR。同时,该后缀还表示传入或传出的是用户模式下的寄存器,而不是当前模式下的寄存器。
指令范例:
STMFD R13!,{R0,R4-R12,LR} ;将寄存器列表中的寄存器(R0,R4 到R12,LR)存入堆栈。
LDMFD R13!,{R0,R4-R12,PC} ;将堆栈内容恢复到寄存器(R0,R4 到R12,LR)。
ARM 微处理器所支持数据交换指令能在内存和寄存器之间交换数据。资料交换指令有如下两条:
SWP 字数据交换指令
SWPB 字节数据交换指令
SWP 指令
SWP 指令的语法为:
SWP{条件} 目的寄存器,来源寄存器1,[来源寄存器2]
SWP 指令用于将来源寄存器2 所指向的内存中的字数据传送到目的寄存器中,同时将来源寄存器1 中的字数据传送到来源寄存器2 所指向的内存中。显然,当来源寄存器1 和目的寄存器为同一个寄存器时,指令交换该寄存器和记忆体的内容。指令范例:
SWP R0,R1,[R2] ;将R2 所指向的内存中的字数据传送到R0,同时将R1 中的字数据传送到R2 所指向的存储单元。
SWP R0,R0,[R1] ;该指令完成将R1 所指向的内存中的字数据与R0 中的字资料交换。
SWPB 指令
SWPB 指令的语法为:
SWP{条件}B 目的寄存器,来源寄存器1,[来源寄存器2]
SWPB指令用于将来源寄存器2 所指向的内存中的字节数据传送到目的寄存器中,目的寄存器的高24 清零,同时将来源寄存器1 中的字节数据传送到来源寄存器2 所指向的内存中。显然,当来源寄存器1 和目的寄存器为同一个寄存器时,指令交换该寄存器和内存的内容。指令范例:
SWPB R0,R1,[R2] ;将R2 所指向的内存中的字节数据传送到R0,R0 的高24位清零,同时将R1 中的低8 位数据传送到R2 所指向的存储单元。
SWPB R0,R0,[R1] ;该指令完成将R1 所指向的内存中的字节数据与R0 中的低8位数据交换。
ARM 微处理器内嵌的桶型移位器(Barrel Shifter),支持数据的各种移位元操作,移位元操作在ARM 指令集中不作为单独的指令使用,它只能作为指令格式中是一个字段,在汇编语言中表示为指令中的选项。例如,数据处理指令的第二个操作数为寄存器时,就可以加入移位元操作选项对它进行各种移位操作。移位操作包括如下6 种类型,ASL 和LSL 是等价的,可以自由互换:
LSL 逻辑左移
ASL 算术左移
LSR 逻辑右移
ASR 算术右移
ROR 循环右移
RRX 带扩充的循环右移44
LSL(或ASL)操作
LSL(或ASL)操作的格式为:
通用寄存器,LSL(或ASL) 操作数
LSL(或ASL)可完成对通用寄存器中的内容进行逻辑(或算术)的左移操作,按操作数所指定的数量向左移位,低位用零来填充。其中,操作数可以是通用寄存器,也可以是立即数(0∼31)。
操作范例:
MOV R0, R1, LSL#2 ;将R1 中的内容左移两位后传送到R0 中。
LSR 操作
LSR 操作的格式为:
通用寄存器,LSR 操作数
LSR 可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用零来填充。其中,操作数可以是通用寄存器,也可以是立即数0∼31)。操作范例:
MOV R0, R1, LSR#2 ;将R1 中的内容右移两位后传送到R0 中,左端用零来填充。
ASR 操作
ASR 操作的格式为:
通用寄存器,ASR 操作数
ASR 可完成对通用寄存器中的内容进行右移的操作,按操作数所指定的数量向右移位,左端用第31 位的值来填充。其中,操作数可以是通用寄存器,也可以是立即数(0∼31)。操作范例:
MOV R0, R1, ASR#2 ;将R1 中的内容右移两位后传送到R0 中,左端用第31 位的值来填充。
ROR 操作
ROR 操作的格式为:
通用寄存器,ROR 操作数45
ROR 可完成对通用寄存器中的内容进行循环右移的操作,按操作数所指定的数量向右循环移位,左端用右端移出的位来填充。其中,操作数可以是通用寄存器,也可以是立即数(0∼31)。显然,当进行32 位的循环右移操作时,通用寄存器中的值不改变。操作范例:
MOV R0, R1, ROR#2 ;将R1 中的内容循环右移两位后传送到R0 中。
RRX 操作
RRX 操作的格式为:
通用寄存器,RRX 操作数
RRX 可完成对通用寄存器中的内容进行带扩充的循环右移的操作,按运算元所指定的数量向右循环移位,左端用进位标志位C 来填充。其中,运算元可以是通用寄存器,也可以是立即数(0∼31)。操作范例:
MOV R0, R1, RRX#2 ;将R1 中的内容进行带扩充的循环右移两位后传送到R0 中。
ARM 微处理器可支持多达16 个协处理器,用于各种协处理操作,在程序执行的过程中,每个协处理器只执行针对自身的协处理指令,忽略ARM 处理器和其它协处理器的指令。ARM的协处理器指令主要用于ARM处理器初始化ARM协处理器的资料处理操作,以及在ARM 处理器的寄存器和协处理器的寄存器之间传送资料,和在ARM 协处理器的寄存器和内存之间传送数据。ARM 协处理器指令包括以下5 条:
CDP 协处理器数操作指令
LDC 协处理器数据加载指令
STC 协处理器数据存储指令46
MCR ARM 处理器寄存器到协处理器寄存器的数据传送指令
MRC 协处理器寄存器到ARM处理器寄存器的数据传送指令
CDP 指令
CDP 指令的语法为:
CDP{条件} 协处理器编码,协处理器操作码1,目的寄存器,来源寄存器1,来源寄存器2,协处理器操作码2。
CDP 指令用于ARM处理器通知ARM协处理器执行特定的操作,若辅助运算器不能成功完成特定的操作,则产生未定义指令例外。其中协处理器操作码1 和协处理器操作码2 为协处理器将要执行的操作,目的寄存器和来源寄存器均为协处理器的寄存器,指令不涉及ARM 处理器的寄存器和内存。指令范例:
CDP P3,2,C12,C10,C3,4 ;该指令完成协处理器P3 的初始化
LDC 指令
LDC 指令的语法为:
LDC{条件}{L} 协处理器编码,目的寄存器,[来源寄存器]
LDC 指令用于将来源寄存器所指向的内存中的字数据传送到目的寄存器中,若协处理器不能成功完成传送操作,则产生未定义指令例外。其中,{L}选项表示指令为长读取操作,如用于双精度数据的传输。指令范例:
LDC P3,C4,[R0] ;将ARM 处理器的寄存器R0 所指向的内存中的字资料传送到协处理器P3 的寄存器C4 中。
STC 指令
STC 指令的语法为:
STC{条件}{L} 协处理器编码,来源寄存器,[目的寄存器]
STC 指令用于将来源寄存器中的字数据传送到目的寄存器所指向的内存中,若协处理器不能成功完成传送操作,则产生未定义指令例外。其中,{L}选项表示指令为长读取操作,如用于双精度数据的传输。指令范例:
STC P3,C4,[R0] ;将协处理器P3 的寄存器C4 中的字数据传送到ARM 处理器的寄存器R0 所指向的内存中。
MCR 指令
MCR 指令的语法为:
MCR{条件} 协处理器编码,协处理器操作码1,来源寄存器,目的寄存器1,目的寄存器2,协处理器操作码2。
MCR 指令用于将ARM 处理器寄存器中的数据传送到协处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令例外。其中协处理器操作码1 和协处理器操作码2 为协处理器将要执行的操作,来源寄存器为ARM处理器的寄存器,目的寄存器1 和目的寄存器2 均为协处理器的寄存器。指令范例:
MCR P3,3,R0,C4,C5,6 ;该指令将ARM 处理器寄存器R0 中的数据传送到辅助运算器P3 的寄存器C4 和C5 中。
MRC 指令
MRC 指令的语法为:
MRC{条件} 协处理器编码,协处理器操作码1,目的寄存器,来源寄存器1,来源寄存器2,协处理器操作码2。
MRC 指令用于将协处理器寄存器中的数据传送到ARM 处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令例外。其中协处理器操作码1 和协处理器操作码2 为协处理器将要执行的操作,目的寄存器为ARM处理器的寄存器,来源寄存器1 和来源寄存器2 均为协处理器的寄存器。指令范例:
MRC P3,3,R0,C4,C5,6 ;该指令将协处理器P3 的寄存器中的数据传送到ARM处理器寄存器中。48
例外产生指令
ARM 微处理器所支持的例外指令有如下两条:
SWI 软件中断指令
BKPT 断点中断指令
SWI 指令
SWI 指令的语法为:
SWI{条件} 24 位的立即数
SWI 指令用于产生软件中断,以便用户程序能使用操作系统的系统例程。作业系统在SWI 的例外处理程序中提供相应的系统服务,指令中24 位的立即数指定用户程序使用系统例程的类型,相关参数透过通用寄存器传递,当指令中24 位的立即数被忽略时,用户程序使用系统例程的类型由通用寄存器R0 的内容决定,同时,参数透过其它通用寄存器传递。指令范例:
SWI 0x02 ;该指令使用操作系统编号位02 的系统例程。
BKPT 指令
BKPT 指令的语法为:
BKPT 16 位的立即数
BKPT 指令产生软件断点中断,可用于程序的除错。
为兼容数据总线宽度为16 位的应用系统,ARM 除了支持执行效率很高的32 位ARM 指令集以外,同时支持16 位的Thumb 指令集。Thumb 指令集是ARM 指令集的一个子集,允许指令编码为16 位的长度。与等价的32 位元程序代码相比较,Thumb 指令集在保留32 程序代码优势的同时,大大的节省了系统的存储空间。
所有的Thumb 指令都有对应的ARM 指令,而且Thumb 的程序模型也对应于ARM 的程序模型,在应用程序的撰写过程中,只要遵循一定使用的规则,Thumb 子程序和ARM 子程序就可以互相使用。当处理器在执行ARM 程序段时,称ARM 处理器处于ARM 工作状态,当处理器在执行Thumb 程序段时,称ARM处理器处于Thumb 工作状态。
与ARM 指令集相比较,Thumb 指令集中的数据处理指令的操作数仍然是32 位,指令地址也为32 位,但Thumb 指令集为实现16 位的指令长度,舍弃了ARM 指令集的一些特性,如大多数的Thumb 指令是无条件执行的,而几乎所有的ARM 指令都是有条件执行的;大多数的Thumb 数据处理指令的目的寄存器与其中一个来源寄存器相同。
由于Thumb 指令的长度为16 位,即只用ARM 指令一半的位数来实现同样的功能,所以,要实现特定的程序功能,所需的Thumb 指令的条数较ARM指令多。在一般的情况下,Thumb 指令与ARM 指令的时间效率和空间效率关系为:
Thumb 程序代码所需的存储空间约为ARM 程序代码的60%∼70%
Thumb 程序代码使用的指令数比ARM 程序代码多约30%∼40%
若使用32 位的内存,ARM 程序代码比Thumb 程序代码快约40%
若使用16 位的内存,Thumb 程序代码比ARM 程序代码快约40%∼50%
与ARM 程序代码相比较,使用Thumb 程序代码,内存的功耗会降低约30%
显然,ARM 指令集和Thumb 指令集各有其优点,若对系统的性能有较高要求,应使用32 位的存储系统和ARM 指令集,若对系统的成本及功耗有较高要求,则应使用16 位的存储系统和Thumb 指令集。当然,若两者结合使用,充分发挥其各自的优点,会取得更好的效果。
|