340 likes | 621 Views
第 七 章 Thumb 微處理器的指令及應用. DMATEK CO.,LTD 深圳市長高科技有限公司. 本章節將介紹 ARM 微處理器 THUMB 指令及其工作原理,一開始我們會先介紹為何要在 32 位元指令中,再設計 16 位元的指令,並說明在那些應用中會使用到 THUMB 的工作模式,最後我們詳細說明每個 THUMB 指令運作方式。 本章的主要內容有: - THUMB 工作模式的應用時機 - THUMB 指令介紹. 7-1 Thumb 微處理器指令描述與說明 應用時機 :
E N D
第七章Thumb微處理器的指令及應用 DMATEK CO.,LTD 深圳市長高科技有限公司
本章節將介紹ARM 微處理器THUMB指令及其工作原理,一開始我們會先介紹為何要在32位元指令中,再設計16位元的指令,並說明在那些應用中會使用到THUMB的工作模式,最後我們詳細說明每個THUMB指令運作方式。 • 本章的主要內容有: • - THUMB工作模式的應用時機 • - THUMB指令介紹
7-1 Thumb微處理器指令描述與說明應用時機: • 為了相容資料匯流排寬度為16位元的應用系統,ARM體系結構除了支援執行效率很高的32位元ARM指令集以外,同時還支援16位元的Thumb指令集。Thumb指令集是通常使用的32位元ARM指令集的子集,每條Thumb指令是16位元長,Thumb指令在標準的ARM暫存器下進行操作。執行時,16位元Thumb指令透明地即時解壓成32位元ARM指令,並且沒有性能損失。這樣,以32位元處理器性能給出16位元程式碼密度,在保留了32位程式碼優勢的同時,大大節省了儲存空間和成本。 • 所有的Thumb指令都有對應的ARM指令,而且Thumb的編寫程式模型也對應於ARM的編寫程式模型,在應用程式的編寫過程中,只要遵循一定的呼叫規則,Thumb副程式和ARM副程式就可以互相呼叫。當處理器在執行ARM程式段時,稱ARM處理器處於ARM工作狀態;當處理器在執行Thumb程式段時,稱ARM處理器處於Thumb工作狀態。與ARM指令集相比較,Thumb指令集中的資料處理指令的運算元仍然是32位元,指令位元址也為32位元,但Thumb指令集為實現16位元的指令長度,捨棄了ARM指令集的一些特性,如大多數的Thumb指令是無條件執行的,而幾乎所有的ARM指令都是有條件執行的;大多數的Thumb資料處理指令的目的暫存器與其中一個來源暫存器相同。由於Thumb指令的長度為16位元,即只用ARM指令一半的位元數來實現同樣的功能,所以,要實現特定的程式功能,所需的Thumb指令的條數比ARM指令多。在一般的情況下,Thumb指令與ARM指令的時間效率和空間效率關係如下:
- Thumb程式碼所需的儲存空間約為ARM程式碼的60%~70%; - Thumb程式碼使用的指令數比ARM程式碼多約30%~40%; - 若使用32位元的記憶體,ARM程式碼比Thumb程式碼快約40%; - 若使用16位元的記憶體,Thumb程式碼比ARM程式碼快約40%~50%; - 與ARM程式碼相比,使用Thumb程式碼,記憶體的功耗會降低約30%。 Thumb指令集與ARM指令集的區別主要有以下幾個方面: - 分支指令。程式相對轉移,特別是條件分支指令與ARM的分支指令相比,在範圍上有更多的限制,轉向副程式只具有無條件的轉移。 - 資料傳送指令。Thumb的資料處理指令對通用暫存器進行操作,在許多情況下,操作的結果必須放入其中一個運算元暫存器中,而不是第三個暫存器中。另外,除CMP指令外,存取R8~R15的Thumb資料處理指令不能更新旗標。
- 單暫存器寫/讀指令。在Thumb狀態下,這些指令只能存取暫存器R0~R7。 - 多暫存器寫/讀指令。採用PUSH和POP指令,以堆疊指標R13作為基址,實現滿遞減堆疊。除可傳送R0~R7外,PUSH還可以儲存連接暫存器(R14),並且POP可以載入程式指標(R15)。 - Thumb指令集沒有輔助運算器指令、信號量指令,以及存取CPSR或SPSR的指令。 • 顯然,ARM指令集和Thumb指令集各有其優點,若對系統的性能有較高要求,則應使用32位元的儲存系統和ARM指令集;若對系統的成本及功耗有較高要求,則應使用16位元的儲存系統和Thumb指令集。當然,若兩者結合使用,則可充分發揮其各自的優點,會取得更好的效果。
7-2 Thumb指令說明: • 7-12.1記憶體存取指令 • (1) LDR和STR--常數偏移 • 載入暫存器和儲存暫存器。記憶體的位址以一個暫存器的內容為基址加上常數偏移量指明,其語法如下: op Rd, [Rn, #immed_5x4] opH Rd, [Rn, #immed_5x4] opB Rd, [Rn, #immed_5x4] • 其中,H指明無符號半字元傳送的參數;B指明無符號位元組傳送的參數;Rd需載入和儲存的暫存器,必須在R0~R7範圍內;immed_5xN為偏移量,這是一個運算式,其取值是N的倍數,在0~31N範圍內。
LDR指令用於從記憶體向暫存器載入一個字元、半字元或位元組;STR指令用於從暫存器讀出一個字元、半字元和位元組儲存到記憶體中。Rn中的內容作為基址,再加上偏移量形成運算元的位址。資料是無符號數,位元組或半字元載入到Rd的最低有效位元組或半字元,其餘位元補0。字元傳送的位址必須可被4整除,半字元傳送的位址必須可被2整除。LDR指令用於從記憶體向暫存器載入一個字元、半字元或位元組;STR指令用於從暫存器讀出一個字元、半字元和位元組儲存到記憶體中。Rn中的內容作為基址,再加上偏移量形成運算元的位址。資料是無符號數,位元組或半字元載入到Rd的最低有效位元組或半字元,其餘位元補0。字元傳送的位址必須可被4整除,半字元傳送的位址必須可被2整除。 • 例如: LDR R3, [R5, #0 STRB R0, [R3, #31] STRH R7, [R3, #16] LDRB R2, [R4, #label{PC}]
(2) LDR和STR—暫存器偏移 • 載入暫存器和儲存暫存器。記憶體的位址以一個暫存器的內容為基址加上暫存器偏移量指明,其語法如下: op Rd, [Rn, Rm] • 其中,op是下列情況之一: -LDR,載入暫存器,4位元組字元; -STR,儲存暫存器,4位元組字元; -LDRH,載入暫存器,2位元組無符號半字元; -LDRSH,載入暫存器,2位元組帶符號半字元;
-STRH,儲存暫存器,2位元組半字元; -LDRB,載入暫存器,無符號位元組; -LDRSB,載入暫存器,帶符號位元組; -STRB,儲存暫存器,位元組; -Rm,內含偏移量的暫存器,Rm必須在R0~R7範圍內。 • STR指令將Rd中的一個字元、半字元或位元組儲存到記憶體,LDR指令從記憶體中將一個字元、半字元或位元組載入到Rd中。指令中Rn的內容為基址加上Rm中的偏移量形成記憶體的位址。對於無符號位元數的載入,Rd的其餘位補0;對於帶符號位元數的載入,Rd的其餘位元複製符號位元。 • 例如: LDR R2, [R1, R5] LDRSH R0, [R0, R6] STRB R1, [R7, R0]
(3) LDR和STR-PC或SP相對偏移 • 載入暫存器和儲存暫存器。用PC或SP中值加上常數偏移量指明記憶體位址,其語法如下: LDR Rd, [PC, #immed_8×4] LDR Rd, label LDR Rd, [SP, #immed_8×4] STR Rd, [SP, #immed_8×4] • 其中,immed_8×4為偏移量,這是一個運算式,取值為4的整數倍,範圍在0~1020內;Label是程式相對偏移運算式,Label必須在當前指令之後且在1KB範圍內;PC或SP的基址加上常數偏移量形成記憶體位址,PC的位元[1]忽略,確保了地址是字元對準的。STR指令沒有PC相對偏移的形式。 • 例如: LDR R2, [PC, #1016] LDR R5, localdata LDR R0, [SP, #920] STR R1, [SP, #20]
(4)PUSH和POP • 暫存器R0~R7及LR進和暫存器R0~R7及PC出,其語法如下: PUSH{reglist) POP {reglist] PUSH{reglist,LR) POP {reglist,PC) • 其中,reglist為R0~R7範圍內的暫存器列表,暫存器間用逗號隔開。指令中的括弧{}與前述不同,它是指令格式的一部分,而不代表暫存器列表可選,暫存器列表中至少有一個暫存器。 • Thumb的堆疊找是採用滿遞減堆疊。堆疊向下生長成長,並且SP指向堆疊的最後入口處。暫存器以數位依編號順序儲存在堆疊中,最低數位編號最低的暫存器其位址最低。
POP{reglist,PC)引起處理器轉移到從堆疊彈出給PC的位址處,這通常是從副程式返回,之前LR應在副程式開頭壓入堆疊。這些指令不影響條件碼旗標。POP{reglist,PC)引起處理器轉移到從堆疊彈出給PC的位址處,這通常是從副程式返回,之前LR應在副程式開頭壓入堆疊。這些指令不影響條件碼旗標。 • 例如: PUSH{R0, R3, R5 } PUSH{R1, R4-R7} PUSH{R0, LR} POP {R2, R5} POP {R0-R71}
(5) LDMIA和STMIA • 載入和儲存多個暫存器,其語法如下: op Rn!,{reglist} • 其中,reglist為R0~R7範圍內的暫存器列表,暫存器間用逗號隔開。暫存器列表中至少有一個暫存器。暫存器以數位依編號順序載入或儲存,最低數位編號最低的暫存器在Rn的初始位址中。Rn中的值以reglist列表中暫存器個數的4倍增加。若Rn在暫存器列表中,則對於LDMIA指令,Rn的最終值是載入的值,不是增加後的地址;對於STMIA指令,Rn的儲存值有兩種情況: • 若Rn是暫存器列表中最低數位編號最低的暫存器,則Rn儲存的值為Rn的初值; • 其他情況則不可預知。 • 例如: LDMIA R3!, {R0, R4} LDMIA R5!, {R0-R7} STMIA R0!, {R6, R7} STMIA R3!, {R3, R5, R7}
7-12.2資料處理指令 • (1) ADD和SUB—低暫存器(R0~R7) • 加法和減法。對於低暫存器操作,這兩條指令各有3種形式,其語法如下: op Rd, Rn, Rm op Rd, Rn, #expr3 op Rd, #expr8 • 其中: • Rd,目的暫存器,在“op Rd,#expr8”形式的指令中也作為第一運算元; • Rn,第一運算元暫存器; • Rm,第二運算元暫存器; • expr3,運算式,其取值為-7~+7範圍內的整數; • expr8,運算式,其取值為-255~+255範圍內的整數; • “opRd,Rn,Rm”形式指令執行Rn+Rm或Rn-Rm操作,結果放在Rd中; • “op Rd,Rn,#expr3”形式指令執行Rn+expr3或Rn-expr3操作,結果放在Rd中; • “opRd,#expr8”形式指令執行Rd+expr8或Rd-expr8操作,結果放在Rd中。
若expr3或expr8為負值的ADD指令,則在組譯時被組譯成對應的帶正數常數的SUB指令;若expr3或expr8為負值的SUB指令,則在組譯時被組譯成對應的帶正數常數的ADD指令,這些指令將根據結果更新旗標N、Z、C和V。若expr3或expr8為負值的ADD指令,則在組譯時被組譯成對應的帶正數常數的SUB指令;若expr3或expr8為負值的SUB指令,則在組譯時被組譯成對應的帶正數常數的ADD指令,這些指令將根據結果更新旗標N、Z、C和V。 • 例如: ADD R3, R1, R5 SUB R0, R4, #5 ADD R7, #201 • (2) ADD--高或低暫存器 • 將暫存器中的值相加,結果送回到第一運算元暫存器,其語法如下: ADD Rd, Rm • 這條指令完成Rd+Rm,結果放到Rd中。若Rd和Rm均為低暫存器,指令將根據執行結果更新旗標N、Z、C和V,其他情況下旗標不變。 • 例如:
(3) ADD和SUB-SP • SP暫存器加或減常數,其語法如下: op SP, #expr • 其中,expr為運算式,取值為-508~+508範圍內4的整數倍。 • 該指令把SP暫存器中的值加上常數expr,結果放入SP暫存器中。指令執行結果不影響條件碼旗標。 • 例如: ADD SP, #31 SUB SP, #96 SUB SP, abc+8 :abc+8的結果必須為-508~+508範圍內4的整數倍
(4) ADD-PC和SP • PC或SP暫存器加一常數,結果放入低暫存器。其語法如下: op Rd, Rp, #expr ADD R12, R4 ADD R10, R11 ADD R2, R4 ;等價於ADD R2,R2,R4 • 其中,expr為運算式,取值為0~1020範圍內4的整數倍。 Rp PC或SP • 該指令把Rp暫存器中的值加上常數expr,結果放入Rd暫存器中。若Rp是PC暫存器,則使用的第一運算元值是(當前指令位元址+4)AND OxFFFFFFFC,指令執行結果不影響條件碼旗標。 • 例如: ADD R6, SP, #64 ADD R2, PC, #980 ADD R0, PC, lit-{PC) ;lit-{PC)的結果必須是0~1020範圍內4的整數倍
(5) ADC、SBC和MUL • 帶進位位元的加法、帶進位位元的減法和乘法。其語法如下: Op Rd,Rm • 其中,Rd是目的暫存器,也是第一個運算元暫存器;Rm是第二個運算元暫存器。Rd和Rm必須是低暫存器(R0~R7)。 • ADC指令完成Rd+Rm,再加進位,結果放入Rd中,用這一條指令可組合成多字元加法。SBC指令完成Rd-Rm,再減相應的借位,結果放入Rd中,用這一條指令可組合成多字元減法。MUL指令完成RdxRm,結果放入Rd中。 • ADC和SBC指令將根據結果更新旗標N、Z、C和V;MUL指令將根據結果更新旗標N和Z,會使C和V不可靠。 • 例如: ADC R2, R4
(6) AND、ORR、EOR和BIC • 按位元邏輯操作,其語法如下: op Rd, Rm • 其中,Rd是目的暫存器,它也是第一運算元暫存器,Rd必須在R0~R7範圍內。Rm是第二運算元暫存器,Rm必須在R0~R7範圍內。 • 這些指令用於對Rd和Rm中的值進行按位元邏輯操作,結果放在Rd暫存器中。AND指令進行邏輯“與”操作,ORR指令進行邏輯“或”操作,EOR指令進行邏輯“互斥或”操作,BIC指令進行“Rd AND NOT Rm”操作。這些指令將根據執行結果更新旗標N和Z。 • 例如: AND R2, R4
(7) ASR、I.SL、LSR和ROR • 移位和迴圈移位操作,其語法如下: op Rd, Rs op Rd, Rm, #expr • 其中,op操作碼,為下列之一: -ASR算術右移。將來源暫存器中的內容看做補數形式的帶符號整數,將符號位元複製到空位; -LSL邏輯左移。空位清為零; -LSR邏輯右移。空位清為零; -ROR迴圈右移。將來源暫存器的最低位移出後,再迴圈移到最高位。ROR僅能有暫存器控制的移位形式(即上面第一種形式)。 • expr,常數移位量,它是一個取值為整數的運算式。整數的範圍如下: -若op是LSR,則其為0~31; -其他情況則為1~32。
若是暫存器控制移位元時,這些指令從Rd中取值,並對其進行移位,結果放回Rd中,Rs的最低有效位元組用做移位元量來控制移位。除ROR外,其他指令有:若是暫存器控制移位元時,這些指令從Rd中取值,並對其進行移位,結果放回Rd中,Rs的最低有效位元組用做移位元量來控制移位。除ROR外,其他指令有: -若移位量為32,則Rd清為零,最後移出的位元保留在旗標C中; -若移位量大於32,則Rd和旗標C均被清為零。 • 對於常數控制移位元形式,指令從Rm中取數,並對其進行移位,結果放到Rd中。 • 這些指令根據執行結果更新旗標N和Z,但不影響旗標V。對於旗標C,若移位元量是零,則不受影響;在其他情況下,則是來源暫存器的最後移出位。 • 例如: ASR R3,R5 LSR R0,R2,#6 LSR R0, R4, #0
(8) CMP和CMN • 比較和比較負值,其語法如下: CMP Rn, #expr CMP Rn, Rm CMN Rn, Rm • 其中,expr為運算式,其值範圍為0~255內的整數。 • 這些指令執行後將根據結果更新條件碼旗標,但不往暫存器中存放結果。CMP指令從Rn中減去expr或Rm的值,CMN指令將Rn和Rm的值相加。對於“CMP Rn,#expr”和“CMN Rn,Rm”指令,Rn和Rm必須是R0~R7之一;對於“CMP Rn,Rm”指令,Rn和Rm則可以是R0~R15中的任何暫存器。 • 例如: CMP R2, #255 CMP R7, R12 CMN R1, R5
(9) MOV、MVN和NEG • 傳送、傳送非和取負,其語法如下: MUV Rd, #expr MOV Rd, Rn MVN Rd, Rm NEG Rd, Rm • 其中,expr為運算式,其值範圍為0~255內的整數。 • MOV指令將expr或Rm中的值放入Rd;MVN指令從Rm中取值,然後對該值進行按位元邏輯“非”操作,結果放入Rd;NEG指令取Rm的值再乘以-1,結果放入Rd。對於“MOV Rd,#expr”、“MVN Rd,Rm”和“NEG Rd,Rm”指令,Rd和Rm必須在R0~R7範圍內;對於“MOV Rd,Rm”指令,Rd和Rm可以是R0~R15中的任何一個。
“MOV Rd,#expr”和“MVN Rd,Rm”指令根據結果更新旗標N和Z,但對旗標C和V無影響;“NEG Rd,Rm”指令根據結果更新旗標N、Z、C和V;“MOV Rd,Rm”指令對旗標位元的影響有兩種情況: • 若Rd或Rm是高暫存器(R8~R15),則不影響旗標位元。 • 若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是第二運算元暫存器,Rn和Rm必須是R0~R7暫存器。 • TST指令對Rm和Rn中的值進行按位“AND”操作。它根據執行結果更新旗標N和Z,但不影響旗標C和V,並且不保留結果。 • 例如: TST R2, R4
7-12.3 分支指令 • (1) B • 分支指令。這是Thumb指令集中唯一的有條件指令。其語法如下: B {cond}label • 其中,label是程式相對偏移運算式,通常是在同一程式碼段內的標號,其要求如下: • 若使用cond,則label必須在當前指令的-252~+256位元組範圍內; • 若指令是無條件的,則label必須在+2KB範圍內。 • 若條件cond滿足或不使用條件cond,則B指令引起處理器轉移到label,label必須在指定的限制內。Thumb指令集的條件碼與ARM指令集的相同。 • 例如: B dloop BEG sectB
(2) BL • 帶鏈結的長分支指令,其語法如下: BL label, • 其中,label是程式相對偏移運算式。 • BL指令將下一條的位址複製到R14(連接暫存器(LR)),並使處理器轉移到label指定的指令處。 • 例如: BL extract
(3) BX • 分支指令,並可選地交換指令集。其語法如下: BX Rm • 其中,Rm裝有分支目的地址,Rm的位[0]不用於位元址部分,若Rm的位元[0]清為零,則其位[1]也必須清為零,並且指令清除CPSR中的旗標T,目的地址的程式碼被解釋為ARM程式碼; • 若Rm的位[0]設置,則目的地址的程式碼被解釋為Thumb程式碼。 • 例如: BX K5
(4) BLX • 帶鏈結分支指令,並可選地交換指令集。其語法如下: BLX Rm BLX label • 其中,Rm裝有分支目的地址,Rm的位[0]不用於位元址部分,若Rm的位元[0]清為零,則其位[1]也必須清為零,並且指令清除CPSR中的旗標T,目的地址的程式碼被解釋為ARM程式碼。 • BLX指令的作用如下: • 複製下一條指令的位元址到R14; • 引起處理器轉移到label或Rm儲存的位址; • 如果Rm的位[0]清為零,或使用“BLX label”形式,則指令集切換到ARM狀態。 • 例如: BLX R6 BLX armsub
7-12.4 中斷和中斷點指令 • (1) SWI • 軟體中斷指令,其語法如下: SWI immed_8 • 其中,immed_8為數字運算式,其取值為0~255範圍內的整數。 • SWI指令引起SWI異常,這意味著處理器狀態切換到ARM狀態,處理器模式切換到管理模式,CPSR保存到管理模式的SPSR中,程式執行轉移到SWI向量位址。 • 處理器忽略immed_8,但immed_8出現在指令操作碼位元[7:0]中,而異常處理程式用它來確定正在請求何種服務。這條指令不影響條件碼旗標。 • 例如: SWI 12
(2) BKPT • 中斷點指令,其語法如下: BKPT immed_8 • 其中,immed_8為數字運算式,其取值為0~255範圍內的整數。 • BKPT指令引起處理器進入除錯模式,除錯工具利用這一點來調查當到達特定位元址的指令時的系統狀態。 • 處理器忽略immed_8,但immed_8出現在指令操作碼位元[7:0]中,除錯器用它來保存有關中斷點的附加資訊。 • 例如: BKPT 67 BKPT 210110
7-12.5 Thumb虛擬指令 • (1) ADR • 該指令將程式相對偏移位址載入到暫存器中,其語法如下: ADR register,expr • 其中,register為載入的暫存器。expr為程式相對偏侈運算式,偏移量必須是正數並小於1KB。expr必須局部定義,不能被導入。 • 在Thumb狀態,ADR僅可以產生字元對準位元址,使用ALIGN指令來確保expr是對準的。expr必須賦值成與ADR虛擬指令在同一個程式碼區域的位址,若它在另一個程式碼區域,則不能保證位址鏈結後會在指令範圍內。 • 例如: ADR R4, exampl ;=>ADD R4,PC,#nn ;code ALlGN example DCW 0, 0, 0, 0
(2) LDR • 該指令用32位元常數或一個位址載入一個低暫存器,其語法如下: LDR register,=[expr | label-exp] • 其中,register為載入的暫存器,僅可以是R0~R7暫存器。 • expr賦值成數字常數: - 若expr值在MOV指令範圍內,則組譯器產生指令; - 若expr值不在MOV指令範圍內,則組譯器將常數放入文字區塊,並產生一條程式相對偏移的LDR指令,從文字區塊中讀常數。 Label-exp,程式相對偏移或外部運算式。 LDR虛擬指令用於兩個主要目的: - 當常數由於超出MOV指令範圍不能載入到暫存器中時,產生文字常數; - 將程式相對偏移或外部位址載入到暫存器中,位址保持有效,與鏈結器將包含LDR的ELF區域放到何處無關。 LDR R1, =0XFFF ;載入0xFFF到Rl中 LDR R2, =labelname ;將labdname的地址載入到R2中
(3) NOP • 該指令產生所需的ARM無操作程式碼,其語法如下: NOP • 狀態旗標不受NOP指令影響。 • 7-3 問題與討論: • 一、 請說明使用THUMB的使用時機。 • 二、為何THUMB並沒有支援有條的執行。 • 三、執行那道指令可以從ARM工作狀態切換到THUMB工作狀態。 • 四、執行那道指令可以從THUMB工作狀態切換到ARM工作狀態。