許多A32和T32的一般數(shù)據(jù)處理具有靈活的第二操作數(shù)(Operand2)。比如下面MOV這條指令:
MOV{S}{cond} Rd, Operand2
那么Operand2可以是什么。Operand2可以有下面兩種形式:
- 常量(取值范圍是受限的)
- 寄存器(可以對其進行移位)
Operand2是一個常量
Operand2作為常量的語法格式
語法格式:
#constant
constant可以是一個表達式,其計算結(jié)果應(yīng)為一個數(shù)值。
- 在A32指令中,constant可以通過對一個8位值的數(shù)旋轉(zhuǎn)右移偶數(shù)個位(32位范圍內(nèi)的)來產(chǎn)生。
例子:
mov r1,#0x00110000
如果是下面這樣,armasm編譯器會報錯,不能用0-255和一個旋轉(zhuǎn)來表示
mov r1,#0x00110011
-
對T32指令則有所不同,有下面四種方式可用的constant:
- 形如0x00XY00XY的常量
- 形如0xXY00XY00的常量
- 形如0xXYXYXYXY的常量
- 對一個8位值左移任意個位數(shù)(32位范圍內(nèi)的)
備注:其中X和Y代表的是16進制的數(shù)字。當然有少數(shù)的指令能擁有的值的范圍比這更廣。
當Operand2和MOVS, MVNS, ANDS, ORRS, ORNS, EORS, BICS, TEQ/TST這些指令一起使用時,如果常量的值大于255并且可以通過移位一個8位值來產(chǎn)生的話,進位標志會被更新為常量的bit[31]。當然如果常量是其他值的話,則不會對進位標志造成影響。
- 指令替代
如果Operand2并不是上面討論的有效值,但是它的邏輯反或者邏輯負是上面討論的有效值的話,則匯編器會根據(jù)該指令產(chǎn)生一條等效的指令,對該變量取反或者取負。
比如對下面這條指令
CMP Rd, #0xFFFFFFFE
匯編器可能會產(chǎn)生一條等效的指令如下:
CMN Rd, #0x2
你可以通過把反匯編代碼和源碼進行比較來確認這一點。
Operand2是一個帶可選移位的寄存器
語法格式:
Rm {, shift}
Rm保存著第二個操作數(shù)的數(shù)據(jù)。
shift是可選的,基于常量或者寄存器控制的移位位數(shù),其格式如下:
- ASR #n; 1 ≤ n ≤ 32
- LSL #n; 1 ≤ n ≤ 31
- LSR #n; 1 ≤ n ≤ 32
- ROR #n; 1 ≤ n ≤ 31
- -;等價于LSL #0表示不移位
- RRX
- type Rs; type是ASR, LSL, LSR, ROR中的一個。Rs只用到Rs最低的那個字節(jié)來提供移位位數(shù)。
備注:type Rs格式只支持A32的指令集。同時移位完的結(jié)果并不會寫回Rm。對某些指令對寄存器進行移位操作可能會更新進位標志(carry flag)。
移位操作
上面介紹了Operand2的移位操作,Operand2是嵌于指令進行使用的。當然移位操作也有單獨的指令進行直接移位操作比如ASR, LSR, LSL, ROR, RRX等這些單獨指令。這兩種移位操作的效果是一樣的,下面分別對這5種移位操作進行介紹。
ASR
ASR(Arithmetic shift right),算術(shù)右移或者可以說是帶符號位的右移(符號位是bit[31])。ASR #n操作可以對寄存器的內(nèi)容進行算術(shù)右移n位,左邊被移走的n位用寄存器的符號位bit[31]進行填充,如圖13-1。
不管是單獨的ASRS指令或者和Operand2(ASR #n)進行配合使用的MOVS, MVNS, ANDS,ORRS, ORNS, EORS, BICS, TEQ , TST這些指令,進位標志會根據(jù)寄存器Rm最后一位被移除掉的位的值bit[n-1]進行更新。比如下面ASR #3的移位示意圖,bit[2]被更新到進位標志中。

備注:當32 <= n,如果需要更新進位標志那么進位標志=bit[31],并且結(jié)果中的所有位都被設(shè)置為bit[31]
例子:
MOV R1,#0X80000001
ASR R0,R1,#3; R0 = (signed)R1>> 3
LSR
LSR(Logical shift right),邏輯右移或者說是無符號的右移。LSR #n操作可以對寄存器的內(nèi)容進行邏輯右移n位,左邊被移走的n位全部被清零,如圖13-2。
不管是單獨的LSRS指令或者和Operand2(LSR #n)進行配合使用的MOVS, MVNS, ANDS,ORRS, ORNS, EORS, BICS, TEQ , TST這些指令,進位標志會根據(jù)寄存器Rm最后一位被移除掉的位的值bit[n-1]進行更新。比如下面LSR #3的移位示意圖,bit[2]被更新到進位標志中。

備注:當33 <= n,如果需要更新進位標志那么進位標志位為0。當32 <= n結(jié)果中的所有位都被設(shè)置為0。
例子:
MOV R1,#0X80000001
LSR R0,R1,#3; R0 = (unsigned)R1>> 3
LSL
LSL(Logical shift left),邏輯左移。LSL #n操作可以對寄存器的內(nèi)容進行邏輯左移n位,右邊被移走的n位全部被清零,如圖13-3。
不管是單獨的LSLS指令或者和Operand2(LSL #n)進行配合使用的MOVS, MVNS,ANDS, ORRS, ORNS, EORS, BICS, TEQ, TST這些指令,進位標志會根據(jù)寄存器Rm最后一位被移除掉的位的值bit[32-n]進行更新。比如下面LSL #3的移位示意圖,bit[29]被更新到進位標志中。

備注:當33 <= n,如果需要更新進位標志那么進位標志位為0。當32 <= n結(jié)果中的所有位都被設(shè)置為0。
例子:
MOV R1,#0X000000ff
LSLS R0,R1,#3
ROR
ROR(Rotate right),循環(huán)右移。ROR #n操作可以把寄存器內(nèi)容的最右邊移出的n位被放到最左邊空出來的n位,如圖13-4。
不管是單獨的RORS指令或者和Operand2(ROR #n)進行配合使用的MOVS,MVNS,ANDS,ORRS, ORNS, EORS, BICS, TEQ, TST這些指令,進位標志會根據(jù)寄存器Rm最后一位被移除掉的位的值bit[n-1]進行更新。比如下面ROR #3的移位示意圖,bit[2]被更新到進位標志中。

備注:n=32時,結(jié)果和最初的Rm值是一樣的,如果進位標志有需要更新那么進位標志=bit[31]。如果32 < n,那么n和n-32其操作的結(jié)果是一樣的。
例子:
MOV R1,#0X000000ff
ROR R0,R1,#3;
RRX
RRX(Rotate right with extend),帶擴展的循環(huán)右移。RRX參與循環(huán)右移的總共有33位,即32位的Rm+進位標志位。但是RRX只按順序循環(huán)右移一位,也就是bit[0]移動到進位標志位,進位標志位循環(huán)移動到bit[31],其他位按順序右移一位,如圖13-5所示。
不管是單獨的RRXS指令或者和Operand2(RRX)進行配合使用的MOVS, MVNS, ANDS,ORRS, ORNS, EORS, BICS, TEQ, TST這些指令,進位標志會根據(jù)寄存器Rm bit[0]進行更新。

例子:
MOV R1,#0X000000ff
RRXS R0,R1
參考資料
【1】DUI0801I_armasm_user_guide
【2】ARM Development Tools