?
4.1? 數(shù)據(jù)處理指令的尋址方式
4.1.1? 數(shù)據(jù)處理指令的尋址方式概要
數(shù)據(jù)處理指令的基本語法格式如下。
<opcode> {<cond>} {S} <Rd>,<Rn>,<shifter_operand>
其中<shifter_operand>有下面11種形式,如表4.1所示。
表4.1??????? <shifter_operand>的尋址方式
語??? 法 |
尋 址 方 式 |
|
1 |
#<immediate> |
立即數(shù)尋址 |
2 |
<Rm> |
寄存器尋址 |
3 |
<Rm>, LSL? #<shift_imm> |
立即數(shù)邏輯左移 |
4 |
<Rm>, LSL? <Rs> |
寄存器邏輯左移 |
5 |
<Rm>, LSR? #<shift_imm> |
立即數(shù)邏輯右移 |
6 |
<Rm>, LSR? <Rs> |
寄存器邏輯右移 |
7 |
<Rm>, ASR? #<shift_imm> |
立即數(shù)算術(shù)右移 |
8 |
<Rm>, ASR? <Rs> |
寄存器算術(shù)右移 |
9 |
<Rm>, ROR? #<shift_imm> |
立即數(shù)循環(huán)右移 |
10 |
<Rm>, ROR? <Rs> |
寄存器循環(huán)右移 |
11 |
<Rm>, RRX |
寄存器擴(kuò)展循環(huán)右移 |
數(shù)據(jù)處理指令的尋址方式根據(jù)<shifter_operand>的不同,相應(yīng)的分為11種。
4.1.2? 指令解碼
圖4.1顯示了數(shù)據(jù)處理指令不同尋址方式下的解碼格式。
圖4.1? 數(shù)據(jù)操作指令編碼格式
編碼格式中各域含義如下。
·? <opcode>:確定具體指令。
·? S:標(biāo)識指令是否影響程序狀態(tài)寄存器CPSR條件標(biāo)志。
·? Rd:指令操作的目的寄存器。
·? Rn:指令第一源操作數(shù)。
·? bit[11∶0]:移位操作,詳見本章移位操作一節(jié)。
·? bit[25]:被用來區(qū)分是立即數(shù)移位操作還是寄存器移位操作。
如果指令編碼出現(xiàn)下面情況:bit[25] = 0并且bit[4] = 1并且bit[7] = 1,則指令并非數(shù)據(jù)處理指令,它可能是Load/Store指令或算術(shù)指令。
4.1.3? 移位操作
數(shù)據(jù)處理指令是在算術(shù)邏輯單元ALU中完成。ARM處理器一個(gè)顯著特征就是可以在操作數(shù)進(jìn)入ALU之前,對操作數(shù)進(jìn)行指定位數(shù)的左移或右移操作。這種功能明顯增強(qiáng)了數(shù)據(jù)處理操作的靈活性。
移位操作可能產(chǎn)生進(jìn)位,更新程序狀態(tài)寄存器CPSR的進(jìn)位標(biāo)志C。移位操作有下面3種基本方式。
1.立即數(shù)方式
沒有任何一條ARM指令可以包含一個(gè)32位的立即數(shù),數(shù)據(jù)處理指令編碼格式中,第二個(gè)操作數(shù)有12位。指令的編碼格式如圖4.1所示。
指令中的立即數(shù)是由一個(gè)8 bit的常數(shù)移動4 bit偶數(shù)位(0,2,4,…,26,28,30)得到的。所以,每一條指令都包含一個(gè)8 bit的常數(shù)X和移位值Y,得到的立即數(shù)=X循環(huán)右移(2×Y)。
注意 |
8位立即數(shù)一定要移偶數(shù)位。 |
下面列舉了一些有效的立即數(shù)。
0xFF、0x104、0xFF0、0x FF00、0x FF000、0x FF000000、0x F000000F
下面是一些無效的立即數(shù)。
0x101、0x102、0x FF1、0x FF04、0x FF003、0x FFFFFFFF、0x F000001F
下面是一些應(yīng)用立即數(shù)的指令。
MOV? r0,#0???????????????? ;送0到r0
ADD? r3,r3,#1????????????? ;r3的值加1
CMP? r7,#1000?????????????? ;r7的值和1000比較
BIC? r9,r8,#0x FF00???????? ;將r8中8~15位清零,結(jié)果保存在r9中
?
2.寄存器方式
寄存器的值可以被直接用于數(shù)據(jù)操作指令,如:
MOV? r2,r0????????????????? ;r0的值送r2
ADD? r4,r3,r2?????????????? ;r2加r3,結(jié)果送r4
CMP? r7,r8????????????????? ;比較r7和r8的值
3.寄存器移位方式
寄存器的值在被送到ALU之前,可以事先經(jīng)過桶形移位寄存器的處理。預(yù)處理和移位發(fā)生在同一周期內(nèi),所以有效的使用移位寄存器,可以增加代碼的執(zhí)行效率。
具體的移位(或者循環(huán)移位)方式有下面幾種。
·? ASR:算術(shù)右移。
·? LSL:邏輯左移。
·? LSR:邏輯右移。
·? ROR:循環(huán)右移。
·? RRX:擴(kuò)展的循環(huán)右移。
以上5種移位方式,移位值均可以由立即數(shù)或寄存器指定。下面是一些在指令中使用了移位操作的例子。
ADD? r2,r0,r1,LSR? #5
MOV? r1,r0,LSL? #2
RSB? r9,r5,r5,LSL? #1
SUB? r1,r2,r0,LSR #4
MOV? r2,r4,ROR? r0
4.1.4? 尋址方式分類詳解
數(shù)據(jù)處理指令的尋址方式根據(jù)<shifter_operand>的不同,相應(yīng)的分為11種。詳見表4.1。下面對各類尋址方式進(jìn)行詳細(xì)說明。
1.#<immediate>
(1)編碼格式
指令的編碼格式如圖4.2所示。
圖4.2? 數(shù)據(jù)處理指令——立即數(shù)尋址編碼格式
立即數(shù)尋址為數(shù)據(jù)處理指令提供了一個(gè)可直接操作的立即數(shù)。立即數(shù)的生成方法見前面章節(jié)介紹。如果移位值為0,則移位進(jìn)位值為程序狀態(tài)寄存器CPSR的C標(biāo)志位;否則,為32-bit立即數(shù)的bit[31]。
(2)操作偽代碼
Shifter_operand = immed_8 Rotate_Right (rotate_imm*2)
if? rotate_imm == 0 then
????? shifter_carry_out = C flag
else? /* rotate_imm != 0*/
????? shifter_carry_out = shifter_operand[31]
(3)說明
① 并不是所有的32-bit立即數(shù)都是可以使用的合法立即數(shù)。只有那些通過將一個(gè)8-bit的立即數(shù)循環(huán)右移偶數(shù)位可以得到的立即數(shù)才可以在指令中使用。
② 有些立即數(shù)可以通過不止一種方法得到。由于立即數(shù)的構(gòu)造方法中移位包含了循環(huán)操作,而循環(huán)移位操作會影響CPSR的條件標(biāo)志位C。因此,同一個(gè)合法的立即數(shù)由于采用了不同的編碼方式,將使這些指令的執(zhí)行產(chǎn)生不同的結(jié)果,這是不能允許的。ARM匯編器按照下面的規(guī)則來生成立即數(shù)的編碼。
·? 當(dāng)立即數(shù)數(shù)值在0和0xFF范圍時(shí),令immed_8=<immediate>,immed_4=0。
·? 其他情況下,匯編編譯器選擇使用immed_4數(shù)值最小的編碼方式。
③? 為了更精確地控制立即數(shù)的生成,可以使用下面的語法格式控制立即數(shù)的生成。
#<immed_8>,<rotate_amout>
其中,<rotate_amout> = 2*rotate_imm
(4)舉例
SUBS? r0,r0,#1????????????????????? ;寄存器r0中的數(shù)值減1,結(jié)果保存到r0
MOV? r0,#0xff00???? ; 0xff00 → r0????? ;將立即數(shù)0xff00放入r0保存
?
2.<Rm>
(1)編碼格式
指令的編碼格式如圖4.3所示。
圖4.3? 數(shù)據(jù)處理指令——寄存器尋址編碼格式
指令的操作數(shù)即為寄存器中的數(shù)值。移位寄存器的進(jìn)位為程序狀態(tài)寄存器CPSR的C標(biāo)志位。
指令的語法格式為:<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>
(2)操作偽代碼
Shifter_operand = Rm
Shifter_carry_out = C Flag
(3)說明
① 從指令的解碼格式來看,寄存器尋址方式和使用立即數(shù)邏輯左移尋址解碼格式是相同的,只是其移位數(shù)為0。
② 如果指令中的Rm或Rn指定為程序計(jì)數(shù)器r15,則操作數(shù)的值為當(dāng)前指令地址加8。
(4)舉例
MOV? r1,r2??? ; r2 → r1
SUB? r0,r1,r2?? ; r1 – r2 → r0
3.<Rm>, LSL? #<shift_imm>
(1)編碼格式
指令的編碼格式如圖4.4所示。
圖4.4? 數(shù)據(jù)處理指令——立即數(shù)邏輯左移尋址編碼格式
指令的操作數(shù)為寄存器Rm的數(shù)值邏輯左移shift_imm位。左移的范圍在0到31之間。左移移出的位用0補(bǔ)齊。進(jìn)位標(biāo)志位是最后移出的位(如果移位數(shù)為0,則為C標(biāo)志位)。
指令的語法格式為:<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSL #<shift_imm>,其中:
·? <Rm>為進(jìn)行邏輯左移操作的寄存器;
·? LSL為邏輯左移操作標(biāo)識;
·? <shift_imm>為邏輯左移位數(shù),范圍為0~31。
(2)操作偽代碼
if? shift_imm == 0 then /*執(zhí)行寄存器操作*/
????? shifter_operand = Rm
????? shifter_carry_out = C flag
else? /*移位寄存器大于零*/
????? shifter_operand = Rm logical_shift_left shift_imm
????? shifter_carry_out = Rm[32 – shift_imm]
(3)說明
① 如果移位立即數(shù)<shift_imm> =0,則該尋址方式為立即數(shù)直接尋址。
② 如果指令中的Rm或Rn指定為程序計(jì)數(shù)器r15,則操作數(shù)的值為當(dāng)前指令地址加8。
(4)舉例
SUB r0,r1,r2,LSL #10??????? ;r1的值減去r2的值左移10bit,結(jié)果放到r0寄存器
MOV r0,r2,LSL #3??????????? ;r2的值左移3bit,結(jié)果放入r0,即r0 = r2×8
?
4.<Rm>, LSL? <Rs>
(1)編碼格式
指令的編碼格式如圖4.5所示。
圖4.5? 數(shù)據(jù)處理指令——寄存器邏輯左移尋址編碼格式
?
寄存器邏輯左移十分適合寄存器值乘2的倍數(shù)操作。
這個(gè)指令是將寄存器Rm的值邏輯左移一定的位數(shù)。位移的位數(shù)由Rs的最低8位bit[7∶0]決定。Rm移出的位用0補(bǔ)齊。進(jìn)位值是移位寄存器最后移出的位,如果移位數(shù)大于0,則進(jìn)位值為0。
(2)語法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSL? <Rs>
其中:
·? <Rm>為指令被移位的寄存器;
·? LSL為邏輯左移操作標(biāo)識;
·? <Rs>為包含邏輯左移位數(shù)的寄存器。
(3)操作偽代碼
if? Rs[7:0] = = 0 then
???? shifter_operand = Rm
???? shifter_carry_out = C flag
else? if? Rs[7:0] < 32 then
???? shifter_operand = Rm? logical_shift_left? Rs[7:0]
???? shifter_carry_out = Rm[32 – Rs[7:0]]
else? if? Rs[7:0] = = 32 then
???? shifter_operand = 0
???? shifter_carry_out = Rm[0]
else? /*Rs的后8位大于零*/
???? shifter_operand = 0
???? shifter_carry_out = 0
(4)說明
如果程序計(jì)數(shù)器r15被用作Rd,Rm,Rn或Rs中的任意一個(gè),則指令的執(zhí)行結(jié)果不可預(yù)知。
(5)舉例
MOV? r0,r2,LSL r3????????? ;r2的值左移r3位,結(jié)果放入r0
ANDS r1,r1,r2,LSL r3????? ;r2的值左移r3位,然后和r1相與,結(jié)果放入r1
5.<Rm>, LSR #<shift_imm>
(1)編碼格式
指令的編碼格式如圖4.6所示。
圖4.6? 數(shù)據(jù)處理指令——立即數(shù)邏輯右移尋址編碼格式
指令的操作數(shù)為寄存器Rm的值右移<shift_imm>位,相當(dāng)于Rm的值除以一個(gè)2的倍數(shù)。<shift_imm>值的范圍為0~31,移位后空出的位添0。循環(huán)器進(jìn)位值為Rm最后移出的位。
(2)語法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSR #<shift_imm>
其中:
·? <Rm>為被移位的寄存器;
·? LSR為邏輯右移操作標(biāo)識;
·? <shift_imm>為邏輯右移位數(shù),范圍為0~31。
(3)操作偽代碼
if? shift_imm == 0 then /*執(zhí)行寄存器操作*/
????? shifter_operand = 0
????? shifter_carry_out = Rm[31]
else? /*移位立即數(shù)大于零*/
????? shifter_operand = Rm logical_shift_Right shift_imm
????? shifter_carry_out = Rm[shift_imm - 1]
(4)說明
① shift_imm的取值范圍為0~31,當(dāng)shift_imm=0時(shí),移位位數(shù)為32,所以移位位數(shù)范圍為1~32位。
② 如果指令中的Rm或Rn指定為程序計(jì)數(shù)器r15,則操作數(shù)的值為當(dāng)前指令地址加8。
?
6.<Rm>, LSR? <Rs>
(1)編碼格式
指令的編碼格式如圖4.7所示。
圖4.7? 數(shù)據(jù)處理指令——寄存器邏輯右移尋址編碼格式
此操作將寄存器Rm的數(shù)值邏輯右移一定的位數(shù)。移位的位數(shù)由Rs的最低8位bit[7∶0]決定。移出的位由0補(bǔ)齊。當(dāng)Rs[7∶0]大于0而小于32時(shí),進(jìn)位標(biāo)志C由最后移出的位決定,當(dāng)Rs[7∶0]大于32時(shí),進(jìn)位標(biāo)志位為0,當(dāng)Rs[7∶0]等于0時(shí),進(jìn)位標(biāo)志不變。
(2)語法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,LSR? <Rs>
其中:
·? <Rm>為指令被移位的寄存器;
·? LSR為邏輯右移操作標(biāo)識;
·? <Rs>為包含邏輯右移位數(shù)的寄存器。
(3)操作偽代碼
if? Rs[7:0] = = 0 then
???? shifter_operand = Rm
???? shifter_carry_out = C flag
else? if? Rs[7:0] < 32 then
???? shifter_operand = Rm? logical_shift_Right? Rs[7:0]
???? shifter_carry_out = Rm[Rs[7:0] - 1]
else? if? Rs[7:0] = = 32 then
???? shifter_operand = 0
???? shifter_carry_out = Rm[31]
else? /*Rs的后8位大于零*/
???? shifter_operand = 0
???? shifter_carry_out = 0
(4)說明
如果程序計(jì)數(shù)器r15被用作Rd、Rm、Rn或Rs中的任意一個(gè),則指令的執(zhí)行結(jié)果不可預(yù)知。
7.<Rm>, ASR #<shift_imm>
(1)編碼格式
指令的編碼格式如圖4.8所示。
圖4.8? 數(shù)據(jù)處理指令——立即數(shù)算術(shù)右移尋址編碼格式
指令的操作數(shù)為寄存器Rm的數(shù)值邏輯右移<shift_imm>位。<shift_imm>的值范圍為0~31,當(dāng)<shift_imm>等于0時(shí),移位位數(shù)為32,所以移位位數(shù)范圍為1~32位。進(jìn)位移位操作后,空出的位添Rm的最高位Rm[31]。進(jìn)位標(biāo)志為Rm最后被移出的數(shù)值。
(2)語法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ASR #<shift_imm>
其中:
·? <Rm>為被移位的寄存器;
·? ASR為算術(shù)右移操作標(biāo)識;
·? <shift_imm>為算術(shù)右移位數(shù),范圍為1~32,當(dāng)shift_imm等于0時(shí)移位位數(shù)為32。
(3)操作偽代碼
if? shift_imm == 0 then /*執(zhí)行寄存器操作*/
???? if? Rm[31] = = 0 then
????????? shifter_operand = 0
????????? shifter_carry_out = Rm[31]
???? else /*Rm[31] = = 1*/
????????? shifter_operand = 0xffffffff
????????? shifter_carry_out = Rm[31]
else? /*shift_imm > 0*/
???? shifter_operand = Rm Arithmetic_shift_Right <shift_imm>
???? shifter_carry_out = Rm[shift_imm - 1]
(4)說明
① 如果指令中的Rm或Rn指定為程序計(jì)數(shù)器r15,則操作數(shù)的值為當(dāng)前指令地址加8。
?
8.<Rm>, ASR? <Rs>
(1)編碼格式
指令的編碼格式如圖4.9所示。
圖4.9? 數(shù)據(jù)處理指令——寄存器算術(shù)右移尋址編碼格式
此操作將寄存器Rm的數(shù)值算術(shù)右移一定的位數(shù)。移位后空缺的位由Rm的符號位(Rm[31])填充。位移的位數(shù)由Rs的最低8位bit[7∶0]決定。當(dāng)Rs[7∶0]大于零而小于32時(shí),指令的操作數(shù)為寄存器Rm的數(shù)值算術(shù)右移Rs[7∶0]位,進(jìn)位標(biāo)志C為Rm最后被移出的位。
(2)語法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ASR? <Rs>
其中:
·? <Rm>為指令被移位的寄存器;
·? ASR為算術(shù)右移操作標(biāo)識;
·? <Rs>為包含算術(shù)右移位數(shù)的寄存器。
(3)操作偽代碼
if? Rs[7:0] = = 0 then
???? shifter_operand = Rm
???? shifter_carry_out = C flag
else? if? Rs[7:0] < 32 then
???? shifter_operand = Rm? Arithmeticl_shift_Right? Rs[7:0]
???? shifter_carry_out = Rm[Rs[7:0] - 1]
else?
???? if? Rm[31] = =0 then
????????? shifter_operand = 0
????????? shifter_carry_out = Rm[31]
??? else?
????????? shifter_operand = 0xffffffff
????????? shifter_carry_out = Rm[31]
(4)說明
如果程序計(jì)數(shù)器r15被用作Rd、Rm、Rn或Rs中的任意一個(gè),則指令的執(zhí)行結(jié)果不可預(yù)知。
9.<Rm>, ROR #<shift_imm>
(1)編碼格式
指令的編碼格式如圖4.10所示。
圖4.10? 數(shù)據(jù)處理指令——立即數(shù)循環(huán)右移尋址編碼格式
指令的操作數(shù)由寄存器Rm的數(shù)值循環(huán)右移一定的位數(shù)得到。移位的位數(shù)由Rs的最低8位bits[7∶0]決定。當(dāng)Rs[7∶0]=0時(shí),指令的操作數(shù)為寄存器Rm的值,循環(huán)器的進(jìn)位值為CPSR中的C條件標(biāo)志位;否則,循環(huán)器的進(jìn)位值為Rm最后被移出的位。
(2)語法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ROR #<shift_imm>
其中:
·? <Rm>為被移位的寄存器;
·? ROR為循環(huán)右移操作標(biāo)識;
·? <shift_imm>為循環(huán)右移位數(shù),范圍為1~31,當(dāng)shift_imm等于0時(shí)執(zhí)行RRX操作。
(3)操作偽代碼
if? shift_imm == 0 then /*執(zhí)行寄存器操作*/
???? 執(zhí)行RRX操作
else
???? shifter_operand = Rm Rotate_Right shift_imm
???? shifter_carry_out = Rm[shift_imm - 1]
(4)說明
如果指令中的Rm或Rn指定為程序計(jì)數(shù)器r15,則操作數(shù)的值為當(dāng)前指令地址加8。
?
10.<Rm>, ROR? <Rs>
(1)編碼格式
指令的編碼格式如圖4.11所示。
圖4.11? 數(shù)據(jù)處理指令——寄存器循環(huán)右移尋址編碼格式
指令的操作數(shù)由寄存器Rm的數(shù)值循環(huán)右移一定的位數(shù)。移位的位數(shù)由Rs的最低8位bits[7∶0]決定。當(dāng)Rs[7∶0]=0時(shí),指令的操作數(shù)為寄存器Rm的值,循環(huán)器的進(jìn)位值為CPSR中的C條件標(biāo)志位;否則,循環(huán)器的進(jìn)位值為Rm最后被移出的位。
(2)語法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,ROR? <Rs>
其中:
·? <Rm>為指令被移位的寄存器;
·? ROR為循環(huán)右移操作標(biāo)識;
·? <Rs>為包含循環(huán)右移位數(shù)的寄存器。
(3)操作偽代碼
if? Rs[7:0] = = 0 then
???? shifter_operand = Rm
???? shifter_carry_out = C flag
else? if? Rs[4:0] == 0 then
???? shifter_operand = Rm
???? shifter_carry_out = Rm[31]
else?
???? shifter_operand = Rm Rotate_Right Rs[4:0]
???? shifter_carry_out = Rm[Rs[4:0] - 1]
(4)說明
如果程序計(jì)數(shù)器r15被用作Rd、Rm、Rn或Rs中的任意一個(gè),則指令的執(zhí)行結(jié)果不可預(yù)知。
11.<Rm>, RRX
(1)編碼格式
指令的編碼格式如圖4.12所示。
圖4.12? 數(shù)據(jù)處理指令——擴(kuò)展右移尋址編碼格式
指令的操作數(shù)為寄存器Rm的數(shù)值右移一位,并用CPSR中的C條件標(biāo)志位填補(bǔ)空出的位。CPSR中的C條件標(biāo)志位則用移出的位代替。
(2)語法格式
<opcode> {<cond>} {S} <Rd>,<Rn>,<Rm>,RRX
其中:
·? <Rm>為指令被移位的寄存器;
·? RRX為擴(kuò)展的循環(huán)右移操作。
(3)操作偽代碼
shifter_operand = (C flag logical_shift_left 31) OR (Rm logical_shift_Right 1)
shifter_carry_out = Rm[0]
(4)說明
① 此種尋址方式的編碼形式和“ROR #0”一致。
② 如果程序計(jì)數(shù)器r15被用作Rd、Rm、Rn或Rs中的任意一個(gè),則指令的執(zhí)行結(jié)果不可預(yù)知。
③ 可以實(shí)現(xiàn)ADC指令的功能。