(1)Thumb 单寄存器数据存取指令(LDR 和STR)
Thumb 单寄存器存取指令是从存储器中取值放到一个寄存器中,或将一个寄存器值存储到存储器中。 在Thumb 状态下,这些指令只能访问低寄存器R0 ~R7。
Thumb 单寄存器数据存取指令二进制编码如图4.4 所示。
这些指令是从ARM 单寄存器存取指令中精心导出的子集,并且与等价的ARM 指令有严格相同的语义。 在所有的指令中,偏移量需要根据数据类型按比例调整。
指令格式如下:
图4.4 Thumb 单寄存器数据存取指令二进制编码
a.在前三种指令格式中,Rn 为基址寄存器,加上偏移量形成操作数的地址。
b.不支持负偏移,#off5 和#off8 分别表示5 位和8 位的立即数偏移。 在所有情况下,指令格式用字节表示偏移。 在指令二进制编码中的5 和8 位偏移需要根据存取的数据类型进行比例调整。
c.与ARM 指令相同,只有load 指令支持符号数。 对于存储指令,有符号和无符号存储有相同的结果。
d.这些指令只能访问R0 ~R7。
e.PC、SP 的相对偏移仅适用字,地址必须为4 的倍数,最大立即数偏移为1 020,立即数不允许为负数,且STR 没有PC 相对偏移。
f.读字节指令不支持自动变址。
1)LDR 和STR 立即数偏移
加载寄存器和存储寄存器。 存储器的地址以一个寄存器的立即数偏移指明。
①指令格式
其中:
H——指明无符号半字传送的参数。
B——指明无符号字节传送的参数。
Rd——加载和存储寄存器,Rd 必须在R0 ~R7 范围内。
Rn——基址寄存器,Rn 必须在R0 ~R7 范围内。
immed_5 ×N 偏移量,它是一个表达式,其取值(在汇编时)是N 的倍数,在0 ~31N 范围内。 N=4,2,1。 N=4,表示是字传送,immed_5 ×N 的取值范围是0 ~(25 -1) ×4;N =2,表示是半字传送,immed_5 ×N 的取值范围是0 ~(25 -1) ×2;N=1,表示字节传送immed_5 ×N的取值范围是0 ~(25 -1) ×1。
②用法
a.STR 指令用于将寄存器中的一个字、半字或字节存储到存储器中。
b.LDR 指令用于从存储器加载一个字、半字或字节到寄存器中。
c.Rn 中的基址加上偏移形成操作数的地址。
注意:立即数偏移的半字和字节加载是无符号的。 数据加载到Rd 的最低有效字或字节,Rd 的其余位补“0”。 字传送的地址必须可被4 整除(即字对齐),半字传送的地址必须可被2整除(即半字对齐)。
③举例
2)LDR 和STR 寄存器偏移
加载寄存器和存储寄存器。 用一个寄存器的基于寄存器偏移指明存储器地址。
①指令格式
op Rd,[Rn,Rm]
其中:
op 是下列情况之一,即
Rm 内含偏移量的寄存器,Rm 必须在R0 ~R7 范围内。
②用法
a.STR 指令将Rd 中的一个字、半字或字节存储到存储器。
b.LDR 指令从存储器中将一个字、半字或字节加载到Rd。
c.Rn 中的基址加上偏移量形成存储器的地址。
注意:寄存器偏移的半字和字节加载可以是带符号或无符号的。 带符号和无符号的存储指令没有区别,一般没有STRS、STRHS 和STRBS 的指令形式。 数据加载到Rd 的最低有效字或字节。 对于无符号加载,Rd 的其余位补“0”,对于带符号加载,Rd 的其余位拷贝符号位。字传送地址必须可被4 整除,半字传送地址必须可被2 整除。
③举例
3)LDR 和STR PC 或SP 相对偏移(www.xing528.com)
加载寄存器和存储寄存器。 用PC 或SP 中值的立即数偏移指明存储器中的地址。
①指令格式
其中:immed_8 ×4 偏移量,它是一个表达式,取值(在汇编时)为4 的整数倍,范围在0 ~1 020内,即在0 ~(28 -1) ×4 范围内。
label 程序相对偏移表达式。 label 必须在当前指令之后且在1 KB 范围内。
②用法
a.STR 指令将一个字存储到存储器中。
b.LDR 指令从存储器中加载一个字。
c.PC 或SP 的基址加上偏移量形成存储器地址。 PC 的位[1]忽略,确保了地址是字对准的。
注意:没有PC 相对偏移的STR 指令。 半字或字节传送没有PC 或SP 相对偏移。 地址必须是4 的整数倍,8 位的偏移量也必须是4 的整数倍,且不允许是负数。
③举例
(2)Thumb 多寄存器数据存取指令
在Thumb 多寄存器数据存取指令中,LDM 和STM 将任何范围为R0 ~R7 的寄存器子集从存储器加载以及存储到存储器中。 PUSH 和POP 指令使用堆栈指针(SP)作为基址实现满递减堆栈。 除了可以传送R0 ~R7 外,PUSH 还可以用于存储链接寄存器LR(r14),并且POP可以用于加载程序指针PC(r15)。
与ARM 指令一样,Thumb 多寄存器数据存取指令可以用于过程调用与返回以及存储器块拷贝。 但为了编码的紧凑性,这两种用法由分开的指令实现,其寻址方式的数量也有所限制。 在其他方面这些指令的性质与等价的ARM 指令相同。
Thumb 多寄存器存取指令的二进制编码如图4.5 所示。
图4.5 Thumb 多寄存器存取指令的二进制编码
指令的块拷贝形式只有使用LDMIA 和STMIA 寻址模式,即Thumb 指令集使用LDM 和STM 指令进行多寄存器的加载和存储操作时,LDM 和STM 指令必须包括后缀,而且只有IA一个后缀。 低寄存器(8 个低寄存器r0 ~r7)中的任何一个可以作为基址寄存器。 寄存器列表可以是这些寄存器的任意子集,因为总是选择回写,所以寄存器列表中不应包括基址寄存器。
堆栈形式使用指令PUSH 和POP,并使用SP(r13)作为基址寄存器,并且也总是使用回写。 堆栈的模式也固定为满栈递减。 寄存器列表除了可以是8 个低寄存器外,链接寄存器LR(r14)可以出现在PUSH 指令中,PC(r15)可以出现在POP 指令中,以优化过程调用及返回程序。
指令格式如下:
<reg list>是寄存器的列表,寄存器范围是r0 ~r7。
下面分别介绍多寄存器传送指令LDMIA 和STMIA、堆栈指令PUSH 和POP。
1)LDMIA 和STMIA
加载和存储多个寄存器。
①指令格式
其中:reg list 为低寄存器(R0 ~R7)或低寄存器范围的、用逗号隔开的列表。 注意:列表中至少应有一个寄存器。②用法
寄存器以寄存器编号顺序加载或存储。 编号最低的寄存器在Rn 的初始地址中。 Rn 的值以reg list 中寄存器个数的4 倍增加。 若Rn 在寄存器列表中,对于LDMIA 指令,Rn 的最终值是加载的值,不是增加后的地址;对于STMIA 指令,Rn 的存储值有两种情况:a.若Rn 是寄存器列表中最低数字的寄存器,则Rn 存储的值为Rn 的初值;b.其他情况,则不可预知。
③举例
2)PUSH 和POP
低寄存器和可选的LR 进栈以及低寄存器和可选的PC 出栈。
①指令格式
其中:reg list 为低寄存器(r0 ~r7)的全部或子集的列表。 指令格式说明中的括号是指令格式的一部分。 它们不代表指令列表可选。 列表中至少必须有一个寄存器。
②用法
Thumb 堆栈是满递减堆栈。 堆栈向下增长,且SP 指向堆栈的最后入口。 寄存器以数字顺序存储在堆栈中,编号最低的寄存器其地址最低。
这条指令引起处理器转移到从堆栈弹出给PC 的地址。 这通常是从子程序返回,其中LR在子程序开头压进堆栈。 该指令不影响条件码标志。
③举例
3)等价的ARM 指令
对于前两种块指令格式,等价的ARM 指令有相同的指令格式。 在后两种指令格式中要以合适的寻址模式来代替POP 和PUSH。
块拷贝:
注意:基址寄存器必须是字对齐的,否则一些系统将忽略地址值的低2 位,而另一些系统会产生未对齐访问异常。 由于所有这些指令都采用基址回写,因此基址寄存器不应出现在寄存器列表中。 编码后reg list 即指令中的位[0 ~7],它的每一位对应一个寄存器,比如位[0]指示r0 寄存器是否传送,位[1]控制r1,等等。 在POP 和PUSH 指令中,R 位控制PC 和LR。在v5T 结构中,装载的PC 的最低位更新Thumb 位,因此,可以直接返回到Thumb 或ARM 调用程序。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。