ARM指令寻址方式之: 数据处理指令的寻址方式
4.1数据处理指令的寻址方式4.1.1数据处理指令的寻址方式概要
数据处理指令的基本语法格式如下。
<opcode> {<cond>} {S} <Rd>,<Rn>,<shifter_operand>
其中<shifter_operand>有下面11种形式,如表4.1所示。
表4.1 <shifter_operand>的寻址方式
语 法
寻 址 方 式
1
#<immediate>
立即数寻址
2
<Rm>
寄存器寻址
3
<Rm>, LSL#<shift_imm>
立即数逻辑左移
4
<Rm>, LSL<Rs>
寄存器逻辑左移
5
<Rm>, LSR#<shift_imm>
立即数逻辑右移
6
<Rm>, LSR<Rs>
寄存器逻辑右移
7
<Rm>, ASR#<shift_imm>
立即数算术右移
8
<Rm>, ASR<Rs>
寄存器算术右移
9
<Rm>, ROR#<shift_imm>
立即数循环右移
10
<Rm>, ROR<Rs>
寄存器循环右移
11
<Rm>, RRX
寄存器扩展循环右移
数据处理指令的寻址方式根据<shifter_operand>的不同,相应的分为11种。
4.1.2指令解码
图4.1显示了数据处理指令不同寻址方式下的解码格式。
图4.1数据操作指令编码格式
编码格式中各域含义如下。
·<opcode>:确定具体指令。
·S:标识指令是否影响程序状态寄存器CPSR条件标志。
·Rd:指令操作的目的寄存器。
·Rn:指令第一源操作数。
·bit:移位操作,详见本章移位操作一节。
·bit:被用来区分是立即数移位操作还是寄存器移位操作。
如果指令编码出现下面情况:bit = 0并且bit = 1并且bit = 1,则指令并非数据处理指令,它可能是Load/Store指令或算术指令。
4.1.3移位操作
数据处理指令是在算术逻辑单元ALU中完成。ARM处理器一个显著特征就是可以在操作数进入ALU之前,对操作数进行指定位数的左移或右移操作。这种功能明显增强了数据处理操作的灵活性。
移位操作可能产生进位,更新程序状态寄存器CPSR的进位标志C。移位操作有下面3种基本方式。
1.立即数方式
没有任何一条ARM指令可以包含一个32位的立即数,数据处理指令编码格式中,第二个操作数有12位。指令的编码格式如图4.1所示。
指令中的立即数是由一个8 bit的常数移动4 bit偶数位(0,2,4,…,26,28,30)得到的。所以,每一条指令都包含一个8 bit的常数X和移位值Y,得到的立即数=X循环右移(2×Y)。
注意
8位立即数一定要移偶数位。
下面列举了一些有效的立即数。
0xFF、0x104、0xFF0、0x FF00、0x FF000、0x FF000000、0x F000000F
下面是一些无效的立即数。
0x101、0x102、0x FF1、0x FF04、0x FF003、0x FFFFFFFF、0x F000001F
下面是一些应用立即数的指令。
MOVr0,#0 ;送0到r0
ADDr3,r3,#1 ;r3的值加1
CMPr7,#1000 ;r7的值和1000比较
BICr9,r8,#0x FF00 ;将r8中8~15位清零,结果保存在r9中
2.寄存器方式
寄存器的值可以被直接用于数据操作指令,如:
MOVr2,r0 ;r0的值送r2
ADDr4,r3,r2 ;r2加r3,结果送r4
CMPr7,r8 ;比较r7和r8的值
3.寄存器移位方式
寄存器的值在被送到ALU之前,可以事先经过桶形移位寄存器的处理。预处理和移位发生在同一周期内,所以有效的使用移位寄存器,可以增加代码的执行效率。
具体的移位(或者循环移位)方式有下面几种。
·ASR:算术右移。
·LSL:逻辑左移。
·LSR:逻辑右移。
·ROR:循环右移。
·RRX:扩展的循环右移。
以上5种移位方式,移位值均可以由立即数或寄存器指定。下面是一些在指令中使用了移位操作的例子。
ADDr2,r0,r1,LSR#5
MOVr1,r0,LSL#2
RSBr9,r5,r5,LSL#1
SUBr1,r2,r0,LSR #4
MOVr2,r4,RORr0
4.1.4寻址方式分类详解
数据处理指令的寻址方式根据<shifter_operand>的不同,相应的分为11种。详见表4.1。下面对各类寻址方式进行详细说明。
1.#<immediate>
(1)编码格式
指令的编码格式如图4.2所示。
图4.2数据处理指令——立即数寻址编码格式
立即数寻址为数据处理指令提供了一个可直接操作的立即数。立即数的生成方法见前面章节介绍。如果移位值为0,则移位进位值为程序状态寄存器CPSR的C标志位;否则,为32-bit立即数的bit。
(2)操作伪代码
Shifter_operand = immed_8 Rotate_Right (rotate_imm*2)
ifrotate_imm == 0 then
shifter_carry_out = C flag
else/* rotate_imm != 0*/
shifter_carry_out = shifter_operand
(3)说明
① 并不是所有的32-bit立即数都是可以使用的合法立即数。只有那些通过将一个8-bit的立即数循环右移偶数位可以得到的立即数才可以在指令中使用。
② 有些立即数可以通过不止一种方法得到。由于立即数的构造方法中移位包含了循环操作,而循环移位操作会影响CPSR的条件标志位C。因此,同一个合法的立即数由于采用了不同的编码方式,将使这些指令的执行产生不同的结果,这是不能允许的。ARM汇编器按照下面的规则来生成立即数的编码。
·当立即数数值在0和0xFF范围时,令immed_8=<immediate>,immed_4=0。
·其他情况下,汇编编译器选择使用immed_4数值最小的编码方式。
③为了更精确地控制立即数的生成,可以使用下面的语法格式控制立即数的生成。
#<immed_8>,<rotate_amout>
其中,<rotate_amout> = 2*rotate_imm
(4)举例
SUBSr0,r0,#1 ;寄存器r0中的数值减1,结果保存到r0
MOVr0,#0xff00 ; 0xff00 → r0 ;将立即数0xff00放入r0保存
2.<Rm>
(1)编码格式
指令的编码格式如图4.3所示。
图4.3数据处理指令——寄存器寻址编码格式
指令的操作数即为寄存器中的数值。移位寄存器的进位为程序状态寄存器CPSR的C标志位。
指令的语法格式为:<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>
(2)操作伪代码
Shifter_operand = Rm
Shifter_carry_out = C Flag
(3)说明
① 从指令的解码格式来看,寄存器寻址方式和使用立即数逻辑左移寻址解码格式是相同的,只是其移位数为0。
② 如果指令中的Rm或Rn指定为程序计数器r15,则操作数的值为当前指令地址加8。
(4)举例
MOVr1,r2 ; r2 → r1
SUBr0,r1,r2 ; r1 – r2 → r0
3.<Rm>, LSL#<shift_imm>
(1)编码格式
指令的编码格式如图4.4所示。
图4.4数据处理指令——立即数逻辑左移寻址编码格式
指令的操作数为寄存器Rm的数值逻辑左移shift_imm位。左移的范围在0到31之间。左移移出的位用0补齐。进位标志位是最后移出的位(如果移位数为0,则为C标志位)。
指令的语法格式为:<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSL #<shift_imm>,其中:
·<Rm>为进行逻辑左移操作的寄存器;
·LSL为逻辑左移操作标识;
·<shift_imm>为逻辑左移位数,范围为0~31。
(2)操作伪代码
ifshift_imm == 0 then /*执行寄存器操作*/
shifter_operand = Rm
shifter_carry_out = C flag
else/*移位寄存器大于零*/
shifter_operand = Rm logical_shift_left shift_imm
shifter_carry_out = Rm
(3)说明
① 如果移位立即数<shift_imm> =0,则该寻址方式为立即数直接寻址。
② 如果指令中的Rm或Rn指定为程序计数器r15,则操作数的值为当前指令地址加8。
(4)举例
SUB r0,r1,r2,LSL #10 ;r1的值减去r2的值左移10bit,结果放到r0寄存器
MOV r0,r2,LSL #3 ;r2的值左移3bit,结果放入r0,即r0 = r2×8
4.<Rm>, LSL<Rs>
(1)编码格式
指令的编码格式如图4.5所示。
图4.5数据处理指令——寄存器逻辑左移寻址编码格式
寄存器逻辑左移十分适合寄存器值乘2的倍数操作。
这个指令是将寄存器Rm的值逻辑左移一定的位数。位移的位数由Rs的最低8位bit决定。Rm移出的位用0补齐。进位值是移位寄存器最后移出的位,如果移位数大于0,则进位值为0。
(2)语法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSL<Rs>
其中:
·<Rm>为指令被移位的寄存器;
·LSL为逻辑左移操作标识;
·<Rs>为包含逻辑左移位数的寄存器。
(3)操作伪代码
ifRs = = 0 then
shifter_operand = Rm
shifter_carry_out = C flag
elseifRs < 32 then
shifter_operand = Rmlogical_shift_leftRs
shifter_carry_out = Rm]
elseifRs = = 32 then
shifter_operand = 0
shifter_carry_out = Rm
else/*Rs的后8位大于零*/
shifter_operand = 0
shifter_carry_out = 0
(4)说明
如果程序计数器r15被用作Rd,Rm,Rn或Rs中的任意一个,则指令的执行结果不可预知。
(5)举例
MOVr0,r2,LSL r3 ;r2的值左移r3位,结果放入r0
ANDS r1,r1,r2,LSL r3 ;r2的值左移r3位,然后和r1相与,结果放入r1
5.<Rm>, LSR #<shift_imm>
(1)编码格式
指令的编码格式如图4.6所示。
图4.6数据处理指令——立即数逻辑右移寻址编码格式
指令的操作数为寄存器Rm的值右移<shift_imm>位,相当于Rm的值除以一个2的倍数。<shift_imm>值的范围为0~31,移位后空出的位添0。循环器进位值为Rm最后移出的位。
(2)语法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSR #<shift_imm>
其中:
·<Rm>为被移位的寄存器;
·LSR为逻辑右移操作标识;
·<shift_imm>为逻辑右移位数,范围为0~31。
(3)操作伪代码
ifshift_imm == 0 then /*执行寄存器操作*/
shifter_operand = 0
shifter_carry_out = Rm
else/*移位立即数大于零*/
shifter_operand = Rm logical_shift_Right shift_imm
shifter_carry_out = Rm
(4)说明
① shift_imm的取值范围为0~31,当shift_imm=0时,移位位数为32,所以移位位数范围为1~32位。
② 如果指令中的Rm或Rn指定为程序计数器r15,则操作数的值为当前指令地址加8。
6.<Rm>, LSR<Rs>
(1)编码格式
指令的编码格式如图4.7所示。
图4.7数据处理指令——寄存器逻辑右移寻址编码格式
此操作将寄存器Rm的数值逻辑右移一定的位数。移位的位数由Rs的最低8位bit决定。移出的位由0补齐。当Rs大于0而小于32时,进位标志C由最后移出的位决定,当Rs大于32时,进位标志位为0,当Rs等于0时,进位标志不变。
(2)语法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSR<Rs>
其中:
·<Rm>为指令被移位的寄存器;
·LSR为逻辑右移操作标识;
·<Rs>为包含逻辑右移位数的寄存器。
(3)操作伪代码
ifRs = = 0 then
shifter_operand = Rm
shifter_carry_out = C flag
elseifRs < 32 then
shifter_operand = Rmlogical_shift_RightRs
shifter_carry_out = Rm - 1]
elseifRs = = 32 then
shifter_operand = 0
shifter_carry_out = Rm
else/*Rs的后8位大于零*/
shifter_operand = 0
shifter_carry_out = 0
(4)说明
如果程序计数器r15被用作Rd、Rm、Rn或Rs中的任意一个,则指令的执行结果不可预知。
7.<Rm>, ASR #<shift_imm>
(1)编码格式
指令的编码格式如图4.8所示。
图4.8数据处理指令——立即数算术右移寻址编码格式
指令的操作数为寄存器Rm的数值逻辑右移<shift_imm>位。<shift_imm>的值范围为0~31,当<shift_imm>等于0时,移位位数为32,所以移位位数范围为1~32位。进位移位操作后,空出的位添Rm的最高位Rm。进位标志为Rm最后被移出的数值。
(2)语法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ASR #<shift_imm>
其中:
·<Rm>为被移位的寄存器;
·ASR为算术右移操作标识;
·<shift_imm>为算术右移位数,范围为1~32,当shift_imm等于0时移位位数为32。
(3)操作伪代码
ifshift_imm == 0 then /*执行寄存器操作*/
ifRm = = 0 then
shifter_operand = 0
shifter_carry_out = Rm
else /*Rm = = 1*/
shifter_operand = 0xffffffff
shifter_carry_out = Rm
else/*shift_imm > 0*/
shifter_operand = Rm Arithmetic_shift_Right <shift_imm>
shifter_carry_out = Rm
(4)说明
① 如果指令中的Rm或Rn指定为程序计数器r15,则操作数的值为当前指令地址加8。
8.<Rm>, ASR<Rs>
(1)编码格式
指令的编码格式如图4.9所示。
图4.9数据处理指令——寄存器算术右移寻址编码格式
此操作将寄存器Rm的数值算术右移一定的位数。移位后空缺的位由Rm的符号位(Rm)填充。位移的位数由Rs的最低8位bit决定。当Rs大于零而小于32时,指令的操作数为寄存器Rm的数值算术右移Rs位,进位标志C为Rm最后被移出的位。
(2)语法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ASR<Rs>
其中:
·<Rm>为指令被移位的寄存器;
·ASR为算术右移操作标识;
·<Rs>为包含算术右移位数的寄存器。
(3)操作伪代码
ifRs = = 0 then
shifter_operand = Rm
shifter_carry_out = C flag
elseifRs < 32 then
shifter_operand = RmArithmeticl_shift_RightRs
shifter_carry_out = Rm - 1]
else
ifRm = =0 then
shifter_operand = 0
shifter_carry_out = Rm
else
shifter_operand = 0xffffffff
shifter_carry_out = Rm
(4)说明
如果程序计数器r15被用作Rd、Rm、Rn或Rs中的任意一个,则指令的执行结果不可预知。
9.<Rm>, ROR #<shift_imm>
(1)编码格式
指令的编码格式如图4.10所示。
图4.10数据处理指令——立即数循环右移寻址编码格式
指令的操作数由寄存器Rm的数值循环右移一定的位数得到。移位的位数由Rs的最低8位bits决定。当Rs=0时,指令的操作数为寄存器Rm的值,循环器的进位值为CPSR中的C条件标志位;否则,循环器的进位值为Rm最后被移出的位。
(2)语法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ROR #<shift_imm>
其中:
·<Rm>为被移位的寄存器;
·ROR为循环右移操作标识;
·<shift_imm>为循环右移位数,范围为1~31,当shift_imm等于0时执行RRX操作。
(3)操作伪代码
ifshift_imm == 0 then /*执行寄存器操作*/
执行RRX操作
else
shifter_operand = Rm Rotate_Right shift_imm
shifter_carry_out = Rm
(4)说明
如果指令中的Rm或Rn指定为程序计数器r15,则操作数的值为当前指令地址加8。
10.<Rm>, ROR<Rs>
(1)编码格式
指令的编码格式如图4.11所示。
图4.11数据处理指令——寄存器循环右移寻址编码格式
指令的操作数由寄存器Rm的数值循环右移一定的位数。移位的位数由Rs的最低8位bits决定。当Rs=0时,指令的操作数为寄存器Rm的值,循环器的进位值为CPSR中的C条件标志位;否则,循环器的进位值为Rm最后被移出的位。
(2)语法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ROR<Rs>
其中:
·<Rm>为指令被移位的寄存器;
·ROR为循环右移操作标识;
·<Rs>为包含循环右移位数的寄存器。
(3)操作伪代码
ifRs = = 0 then
shifter_operand = Rm
shifter_carry_out = C flag
elseifRs == 0 then
shifter_operand = Rm
shifter_carry_out = Rm
else
shifter_operand = Rm Rotate_Right Rs
shifter_carry_out = Rm - 1]
(4)说明
如果程序计数器r15被用作Rd、Rm、Rn或Rs中的任意一个,则指令的执行结果不可预知。
11.<Rm>, RRX
(1)编码格式
指令的编码格式如图4.12所示。
图4.12数据处理指令——扩展右移寻址编码格式
指令的操作数为寄存器Rm的数值右移一位,并用CPSR中的C条件标志位填补空出的位。CPSR中的C条件标志位则用移出的位代替。
(2)语法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,RRX
其中:
·<Rm>为指令被移位的寄存器;
·RRX为扩展的循环右移操作。
(3)操作伪代码
shifter_operand = (C flag logical_shift_left 31) OR (Rm logical_shift_Right 1)
shifter_carry_out = Rm
(4)说明
① 此种寻址方式的编码形式和“ROR #0”一致。
② 如果程序计数器r15被用作Rd、Rm、Rn或Rs中的任意一个,则指令的执行结果不可预知。
③ 可以实现ADC指令的功能。
页:
[1]