Thumb指令
Thumb指令
thumb指令集是arm指令集的一個子集,是針對代碼密度問題而提出的,它具有16位的代碼寬度。與等價的32位代碼相比較,thumb指令集在保留32位代碼優勢的同時,大大的節省了系統的存儲空間。thumb不是一個完整的體系結構,不能指望處理器只執行thumb指令集而不支持arm指令集。
thumb指令集分為:分支指令、數據傳送指令、單寄存器載入和存儲指令以及多寄存器載入和存儲指令。thumb指令集沒有協處理器指令、信號量(semaphore)指令以及訪問cpsr或spsr的指令。
1.存儲器訪問指令
(1)dr和str--立即數偏移 載入寄存器和存儲寄存器。存儲器的地址以一個寄存器的立即數偏移(immediate offset)指明。
指令格式:
op rd, rn,#immed_5×4]
oph rd, rn,#immed_5×2]
opb rd, rn,#immed_5×1]
其中:
op:為dr或str。
h:指明無符號半字傳送的參數。
b:指明無符號位元組傳送的參數。
rd:載入和存儲寄存器。rd 必須在r0~r7範圍內。
rn:基址寄存器。rn 必須在r0~r7範圍內。 immed_5×n:偏移量。它是一個表達式,其取值(在彙編時)是n的倍數,在(0~31)*n範圍內,n=4、2、1。
str:用於存儲一個字、半字或位元組到存儲器中。
dr:用於從存儲器載入一個字、半字或位元組。
rn:rn中的基址加上偏移形成操作數的地址。
立即數偏移的半字和位元組載入是無符號的。數據載入到rd的最低有效字或位元組,rd 的其餘位補0。
字傳送的地址必須可被4整除,半字傳送的地址必須可被2整除。
指令示例:
dr r3,5,#0] strb r0,3,#31] strh r7,3,#16] drb r2,4,#1abe-{pc}
(2)dr和str--寄存器偏移 載入寄存器和存儲寄存器。用一個寄存器的基於寄存器偏移指明存儲器地址。指令格式:
op rd,n,rm]
其中,op 是下列情況之一:
dr:載入寄存器,4位元組字。
str:存儲寄存器,4位元組字。
drh:載入寄存器,2位元組無符號半字。
drsh:載入寄存器,2位元組帶符號半字。
strh:存儲寄存器,2位元組半字。
drb:載入寄存器,無符號位元組。
drsb:載入寄存器,帶符號位元組。
strb:存儲寄存器,位元組。
rm:內含偏移量的寄存器,rm必須在r0~r7範圍內。
帶符號和無符號存儲指令沒有區別。
str指令將rd中的一個字、半字或位元組存儲到存儲器。
dr指令從存儲器中將一個字、半字或位元組載入到rd。
rn中的基址加上偏移量形成存儲器的地址。
寄存器偏移的半字和位元組載入可以是帶符號或無符號的。數據載入到rd的最低有效字或位元組。對於無符號載入,rd的其餘位補0;或對於帶符號載入,rd的其餘位複製符號位。字傳送地址必須可被4整除,半字傳送地址必須可被2整除。
指令示例:
dr r2,,r5] drsh r0,0,r6] strb r,7,r0]
(3)dr和str--pc或sp相對偏移 載入寄存器和存儲寄存器。用pc或sp中值的立即數偏移指明存儲器中的地址。沒有pc相對偏移的str指令。
指令格式:
dr rd,c,#immed_8×4]
dr rd,be
dr rd,sp,#immed_8×4]
str rd, p,#immed_8×4]
其中:
immed_8×4:偏移量。它是一個表達式,取值(在彙編時)為4的整數倍,範圍在0~1020之間。
abe:程序相對偏移表達式。abe必須在當前指令之後且1kb範圍內。
str:將一個字存儲到存儲器。
dr:從存儲器中載入一個字。
pc或sp的基址加上偏移量形成存儲器地址。pc的位]被忽略,這確保了地址是字對準的。字或半字傳送的地址必須是4的整數倍。
指令示例:
dr r2,c,#1016] dr r5,ocadata dr r0,p,#920] str r,p,#20]
(4)push和pop 低寄存器和可選的r進棧以及低寄存器和可選的pc出棧。
指令格式:
push {regist}
pop {regist}
push {regist,r}
pop {regist,pc}
其中:
regist:低寄存器的全部或其子集。括弧是指令格式的一部分,它們不代表指令列表可選。列表中至少有1個寄存器。thumb堆棧是滿遞減堆棧,堆棧向下增長,且sp指向堆棧的最後入口。寄存器以數字順序存儲在堆棧中。最低數字的寄存器存儲在最低地址處。
pop {regist,pc}這條指令引起處理器轉移到從堆棧彈出給pc的地址,這通常是從子程序返回,其中r在子程序開頭壓進堆棧。這些指令不影響條件碼標誌。
指令示例: push {r0,r3,r5} push {r1,r4-r7} push {r0,r} pop {r2,r5} pop {r0-r7,pc}
(5)dmia和stmia 載入和存儲多個寄存器。
指令格式:
op rn!,{regist}
其中:
op為dmia或stmia。
regist為低寄存器或低寄存器範圍的、用逗號隔開的列表。括弧是指令格式的一部分,它們不代表指令列表可選,列表中至少應有1個寄存器。寄存器以數字順序載入或存儲,最低數字的寄存器在rn的初始地址中。
rn的值以regist中寄存器個數的4 倍增加。若rn在寄存器列表中,則:
對於dmia指令,rn的最終值是載入的值,不是增加后的地址。
對於stmia指令,rn存儲的值有兩種情況:
若rn是寄存器列表中最低數字的寄存器,則rn存儲的值為rn的初值;其他情況則不可預知,當然,regist中最好不包括rn。
指令示例: dmia r3!,{r0,r4} dmia r5!,{r0~r7} stmia r0!,{r6,r7} stmia r3!,{r3,r5,r7}
2. 數據處理指令
(1)add和sub--低寄存器 加法和減法。對於低寄存器操作,這2條指令各有如下3種形式:
兩個寄存器的內容相加或相減,結果放到第3個寄存器中。
寄存器中的值加上或減去一個小整數,結果放到另一個不同的寄存器中。
寄存器中的值加上或減去一個大整數,結果放回同一個寄存器中。
指令格式:
op rd,rn,rm
op rd,rn,#expr3
op rd,#expr8
其中:
op為add或sub。
rd:目的寄存器。它也用做“op rd,#expr8”的第1個操作數。
rn:第一操作數寄存器。
rm:第二操作數寄存器。
expr3:表達式,為取值在-7~+7範圍內的整數(3位立即數)。
expr8:表達式,為取值在-255~+255範圍內的整數(8位立即數)。
“op rd,rn,rm”執行rn+rm或rn-rm操作,結果放在rd中。
“op rd,rn,#expr3”執行rn+expr3或rn-expr3操作,結果放在rd中。
“op rd,#expr8”執行rd+expr8或rd-expr8操作,結果放在rd中。
expr3或expr8為負值的add指令彙編成相對應的帶正數常量的sub指令。expr3或expr8為負值的sub指令彙編成相對應的帶正數常量的add指令。
rd、rn和rm必須是低寄存器(r0~r7)。
這些指令更新標誌n、z、c和v。
指令示例: add r3,r,r5 sub r0,r4,#5 add r7,#201
(2)add--高或低寄存器 將寄存器中值相加,結果送回到第一操作數寄存器。
指令格式:
add rd,rm
其中:
rd:目的寄存器,也是第一操作數寄存器。
rm:第二操作數寄存器。
這條指令將rd和rm中的值相加,結果放在rd中。
當rd和rm都是低寄存器時,指令“add rd,rm”彙編成指令“add rd,rd,rm”。若rd和rm是低寄存器,則更新條件碼標誌n、z、c 和v;其他情況下這些標誌不受影響。
指令示例: add r12,r4
(3)add和sub--sp sp加上或減去立即數常量。
指令格式:
add sp,#expr
sub sp,#expr
其中:
expr為表達式,取值(在彙編時)為在-508~+508範圍內的4的整倍數。
該指令把expr的值加到sp 的值上或用sp的值減去expr的值,結果放到sp中。
expr為負值的add指令彙編成相對應的帶正數常量的sub指令。expr為負值的sub指令彙編成相對應的帶正數常量的add指令。
這條指令不影響條件碼標誌。
指令示例: add sp,#32 sub sp,#96
(4)add--pc或sp相對偏移 sp或pc值加一立即數常量,結果放入低寄存器。
指令格式: add rd,rp,#expr
其中:
rd:目的寄存器。rd必須在r0~r7範圍內。
rp:sp 或pc。 expr:表達式,取值(彙編時)為在0~1020範圍內的4的整倍數。
這條指令把expr加到rp的值中,結果放入rd。
若rp是pc,則使用值是(當前指令地址+4)and &ffffffc,即忽略地址的低2位。
這條指令不影響條件碼標誌。
指令示例: add r6,sp,#64 add r2,pc,#980
(5)adc、sbc和mu 帶進位的加法、帶進位的減法和乘法。
指令格式:
op rd,rm
其中:
op為adc、sbc或mu。
rd:目的寄存器,也是第一操作數寄存器。
rm:第二操作數寄存器,rd、rm必須是低寄存器。
adc 將帶進位標誌的rd和rm的值相加,結果放在rd中,用這條指令可組合成多字加法。
sbc考慮進位標誌,從rd值中減去rm的值,結果放入rd中,用這條指令可組合成多字減法。
mu進行rd和rm值的乘法,結果放入rd 中。
rd和rm必須是低寄存器(r0~r7)。
adc和sbc更新標誌n、z、c和v。mu更新標誌n和z。
在armv4及以前版本中,mu會使標誌c和v不可靠。在armv5及以後版本中,mu不影響標誌c和v。
指令示例: adc r2,r4 sbc r0,r1 mu r7,r6
(6)按位邏輯操作and、orr、eor和bic
指令格式: op rd,rm
其中:
op為and、orr、eor或bic。
rd:目的寄存器,它也包含第一操作數,rd必須在r0~r7範圍內。
rm:第二操作數寄存器,rm 必須在r0~r7範圍內。
這些指令用於對rd和rm中的值進行按位邏輯操作,結果放在rd 中,操作如下:
and:進行邏輯“與”操作。
orr:進行邏輯“或”操作。
eor:進行邏輯“異或”操作。
bic:進行“rd and not rm”操作。
這些指令根據結果更新標誌n和z。
程序示例: and r1,r2 orr r0,r1 eor r5,r6 bic r7,r6
(7)移位和循環移位操作asr、s、sr和ror thumb指令集中,移位和循環移位操作作為獨立的指令使用,這些指令可使用寄存器中的值或立即數移位量。
指令格式:
op rd,rs
op rd,rm,#expr
其中:
op是下列其中之一:
asr:算術右移,將寄存器中的內容看做補碼形式的帶符號整數。將符號位複製到空出位。
s:邏輯左移,空出位填零。
sr:邏輯右移,空出位填零。
ror:循環右移,將寄存器右端移出的位循環移回到左端。ror僅能與寄存器控制的移位一起使用。
rd:目的寄存器,它也是寄存器控制移位的源寄存器。rd必須在r0~r7範圍內。
rs:包含移位量的寄存器,rs必須在r0~r7範圍內。
rm:立即數移位的源寄存器,rm必須在r0~r7範圍內。
expr:立即數移位量,它是一個取值(在彙編時)為整數的表達式。整數的範圍為:若op是s,則為0~31;其他情況則為1~32。
對於除ror以外的所有指令:
若移位量為32,則rd清零,最後移出的位保留在標誌c中。
若移位量大於32,則rd和標誌c均被清零。
這些指令根據結果更新標誌n和z,且不影響標誌v。對於標誌c,若移位量是零,則不受影響。其他情況下,它包含源寄存器的最後移出位。
指令示例: asr r3,r5 sr r0,r2,#16 ;將r2的內容邏輯右移16次后,結果放入r0中 sr r5,r5,av
(8)比較指令cmp 和cmn
指令格式:
cmp rn,#expr
cmp rn,rm
cmn rn,rm
其中:
rn:第一操作數寄存器。
expr:表達式,其值(在彙編時)為在0~255 範圍內的整數。
rm:第二操作數寄存器。
cmp指令從rn的值中減去expr或rm的值,cmn指令將rm和rn的值相加,這些指令根據結果更新標誌n、z、c和v,但不往寄存器中存放結果。
對於“cmp rn,#expr”和cmn指令,rn和rm必須在r0~r7範圍內。
對於“cmp rn,rm”指令,rn和rm可以是r0~r15中的任何寄存器。
指令示例: cmp r2,#255 cmp r7,r12 cmn r,r5
(9)傳送、傳送非和取負(mov、mvn和neg)
指令格式:
mov rd,#expr
mov rd,rm
mvn rd,rm
neg rd,rm
其中:
rd:目的寄存器。
expr:表達式,其取值為在0~255範圍內的整數。
rm:源寄存器。
mov指令將#expr或rm的值放入rd。mvn指令從rm中取值,然後對該值進行按位邏輯“非”操作,結果放入rd。neg指令取rm的值再乘以-1,結果放入rd。
對於“mov rd,#expr”、mvn和neg指令,rd和rm必須在r0~r7範圍內。
對於“mov rd,rm”指令,rd和rm可以是寄存器r0~r15中的任意一個。
“mov rd,#expr”和mvn 指令更新標誌n和z,對標誌c或v無影響。neg指令更新標誌n、z、c 和v。“mov rd,rm”指令中,若rd或rm是高寄存器(r8~r18),則標誌不受影響;若rd 和rm 都是低寄存器(r0~r7),則更新標誌n和z,且清除標誌c和v。
指令示例: mov r3,#0 mov r0,r12 mvn r7,r1 neg r2,r2
(10)測試位tst
指令格式:
tst rn,rm
其中:
rn:第一操作數寄存器。
rm:第二操作數寄存器。
tst對rm和rn中的值進行按位“與”操作。但不把結果放入寄存器。該指令根據結果更新標誌n和z,標誌c和v不受影響。rn和rm必須在r0~r7範圍內。
指令示例: tst r2,r4
3. 分支指令
(1)分支b指令 這是thumb指令集中唯一的有條件指令。
指令格式:
b{cond} abe
其中:
abe是程序相對偏移表達式,通常是在同一代碼塊內的標號。若使用cond,則abe必須在當前指令的-256~+256位元組範圍內。若指令是無條件的,則abe必須在±2kb範圍內。若cond滿足或不使用cond,則b指令引起處理器轉移到abe。
abe必須在指定限制內。arm鏈接器不能增加代碼來產生更長的轉移。
指令示例: b doop beg sectb
(2)帶鏈接的長分支b指令
指令格式:
b abe
其中,1abe為程序相對轉移表達式。b指令將下一條指令的地址複製到r14(鏈接寄存器),並引起處理器轉移到1abe。
b指令不能轉移到當前指令±4mb以外的地址。必要時,arm鏈接器插入代碼以允許更長的轉移。
指令示例: b extract
(3)分支,並可選地切換指令集bx
指令格式:
bx rm
其中:
rm裝有分支目的地址的arm寄存器。rm的位]不用於地址部分。若rm 的位]清零,則位]也必須清零,指令清除cpsr中的標誌t,目的地址的代碼被解釋為arm代碼,bx指令引起處理器轉移到rm存儲的地址。若rm的位]置位,則指令集切換到thumb狀態。
指令示例: bx r5
(4)帶鏈接分支,並可選地交換指令集bx 指令格式: bx rm bx abe 其中,rm 裝有分支目的地址的arm寄存器。rm的位]不用於地址部分。若rm 的位]清零,則位]必須也清零,指令清除cpsr中的標誌t,目的地址的代碼被解釋為arm代碼。abe為程序相對偏移表達式,“bx abe”始終引起處理器切換到arm狀態。 bx指令可用於:複製下一條指令的地址到r14。引起處理器轉移到abe或rm存儲的地址。如果rm的位]清零,或使用“bx abe”形式,則指令集切換到arm狀態。指令不能轉移到當前指令±4mb範圍以外的地址。必要時,arm鏈接器插入代碼以允許更長的轉移。指令示例: bx r6 bx armsub
4. 中斷和斷點指令
(1)軟體中斷swi指令
指令格式:
swi immed_8
其中,immed_8為數字錶達式,其取值為0~255範圍內的整數。 swi指令引起swi異常。這意味著處理器狀態切換到arm態;處理器模式切換到管理模式,cpsr保存到管理模式的spsr中,執行轉移到swi向量地址。處理器忽略immed_8,但immed_8出現在指令操作碼的位:0]中,而異常處理程序用它來確定正在請求何種服務,這條指令不影響條件碼標誌。
指令示例: swi 12
(2)斷點bkpt指令
指令格式:
bkpt immed_8
其中,immed_8為數字錶達式,取值為0~255範圍內的整數。
bkpt指令引起處理器進入調試模式。調試工具利用這一點來調查到達特定地址的指令時的系統狀態。儘管immed_8出現在指令操作碼的位:0]中,處理器忽略immed_8。調試器用它來保存有關斷點的附加信息。
指令示例: bkpt 67
1、thumb指令繼承了arm指令集的許多特點 thumb指令也是採用load/store結構,有數據處理、數據傳送及流控制指令等。
2、thumb指令集丟棄了arm指令集一些特性 大多數thumb指令是無條件執行的(除了轉移指令b),而所有arm指令都是條件執行的。許多thumb數據處理指令採用2地址格式,即目的寄存器與一個源寄存器相同,而大多數arm數據處理指令採用的是3地址格式(除了64位乘法指令外)。
3、thumb異常時表現的一些特點 所有異常都會使微處理器返回到arm模式狀態,並在arm的編程模式中處理。由於arm微處理器字傳送地址必須可被4整除(即字對準),半字傳送地址必須可被2整除(即半字對準)。而thumb指令是2個位元組長,而不是4個位元組,所以,由thumb執行狀態進入異常時其自然偏移與arm不同。
1、在任何時刻,cpsr的第5位(位t)決定了arm微處理器執行的是arm指令流還是thumb指令流。當t置1,則認為是16位的thumb指令流;當t置0,則認為是32位的arm指令流。
2、進入thumb模式
3、進入thumb指令模式有兩種方法:一種是執行一條交換轉移指令bx,另一種方法是利用異常返回,也可以把微處理器從arm模式轉換為thumb模式。
4、退出thumb模式 退出thumb指令模式也有兩種方法:一種是執行thumb指令中的交換轉移bx指令可以顯式的返回到arm指令流。另一種是利用異常進入arm指令流。
thumb數據處理指令包括一組高度優化且相當複雜的指令,範圍涵蓋編譯器通常需要的大多數操作。arm指令支持在單條指令中完成一個操作數的移位及一個alu操作,但thumb指令集將移位操作和alu操作分離為不同的指令。本部分從以下幾個方面介紹:數據處理指令的二進位編碼 數據處理指令的分類 arm指令與thumb指令比較 數據處理指令的二進位編碼如下圖:
按照數據處理指令的功能,可以將其分為以下幾類:
add與sub—低寄存器加法和減法
add—高或低寄存器
add與sub—sp
add—pc或sp相對偏移
adc,sbc和mul
arm指令與thumb指令低寄存器比較:
arm指令與thumb指令高寄存器比較: