ARM指令集介绍
ARM指令介紹
ARM 指令集是針對ARM體系架構(gòu)設(shè)計(jì)的指令。在BootLoader引導(dǎo)的第一階段以及內(nèi)核的第一階段都會(huì)有一個(gè)使用匯編語言編寫的文件,在不跑操作系統(tǒng)的裸板中也有一段用來初始化開發(fā)板環(huán)境的匯編代碼。所以無論是開發(fā)帶操作系統(tǒng)的板子,還是裸板開發(fā),匯編語言都很有必要學(xué)習(xí)一番,最少要了解一些常用的匯編指令。要想設(shè)計(jì)出性能超強(qiáng)的系統(tǒng),ARM的工作原理是必須掌握的。
ARM指令集可以分為以下六種
- 跳轉(zhuǎn)指令
- 數(shù)據(jù)處理指令
- 程序狀態(tài)寄存器傳輸指令
- Load/Store指令
- 協(xié)處理器指令
- 異常中斷指令
典型的arm指令語法是:< opcode > {< cond >} {s} < Rd >, < Rn >,< shifter_operand >
- < opcode >:指令助記符,如ADD、SUB等指令。
- {< cond >}:表示條件執(zhí)行1。
- {S}:決定指令的操作是否影響CPSR的值。
- < Rd >:目標(biāo)寄存器。
- < Rn >:表示包含第一個(gè)操作數(shù)的寄存器。
- < shifter_operand >:表示第二個(gè)操作數(shù)。
ARM指令的尋址方式
ARM指令尋址指的是尋找操作數(shù)的地址。尋址方式可以分為:
- 數(shù)據(jù)處理指令操作數(shù)的尋址方式。
- Load/Store指令的尋址方式。
數(shù)據(jù)處理指令的操作數(shù)尋址
這些指令的操作數(shù)有3種格式:立即數(shù)2、寄存器方式(操作數(shù)即為寄存器的數(shù)值)、寄存器移位方式(操作數(shù)為寄存器中的值做相應(yīng)的移位)。寄存器移位方式3中有:ASR(算術(shù)右移)、LSL(邏輯左移)、LSR(邏輯右移)、ROR(循環(huán)右移)、RRX(帶擴(kuò)展的循環(huán)右移),移位的位數(shù)可以使用立即數(shù)也可以使用寄存器方式表示。 所以數(shù)據(jù)處理指令尋址方式有11種。
- #< immediate >
- < Rm >
- < Rm >,LSL,#<shirt_imm>
- < Rm >,LSL,#< Rs>
- < Rm >,LSR,#< shirt_imm>
- < Rm >,LSR,#< Rs>
- < Rm >,ASR,#< shirt_imm>
- < Rm >,ASR,#< Rs>
- < Rm >,ROR,#< shirt_imm>
- < Rm >,ROR,#< Rs>
- < Rm >,RRX
load/store操作數(shù)尋址
字及無符號字節(jié)的load/store指令尋址
load/store指令的尋址方式由兩部分組成。一部分為一個(gè)基址寄存器,另一部分為一個(gè)地址偏移量。地址偏移量有3種格式:立即數(shù)、寄存器、寄存器移位。同樣尋址方式的地址計(jì)算方法有3種:普通的偏移量、事先更新方法、事后更新方法。
- 普通的偏移量方法就是基址寄存器中的數(shù)值直接和偏移量做加減運(yùn)算,表示為[ < Rn >,地址偏移量 ]。
- 事先更新方法:先更新再使用,表示為[ < Rn >, 地址偏移量]! ,使用!表示事先更新方法。
- 事后更新方法:使用基址寄存器中的值后再更新,表示為[ < Rn >], 地址偏移量,在[ ],后面跟地址偏移量表示事后更新。
所以可以組合出9種尋址方式: - [ < Rn >,#+/-< offset_12>]
- [ < Rn>,+/-< Rm>]
- [< Rn>,+/-< Rm>,< shift>#< shift_imm>]
- [ < Rn >,#+/-< offset_12>]!
- [ < Rn>,+/-< Rm>]!
- [< Rn>,+/-< Rm>,< shift>#< shift_imm>]!
- [ < Rn >],#+/-< offset_12>
- [ < Rn>],+/-< Rm>
- [< Rn>],+/-< Rm>,< shift>#< shift_imm>
事先更新法和事后更新法指的是操作過程中是先把基址寄存器中的值和偏移值處理后,再使用。還是使用基址寄存器中的值后在更新基址寄存器。類似于C語言中的++val和val++。
批量load/store尋址方式
在需要加載或者是存儲(chǔ)大量數(shù)據(jù)的時(shí)候,可以使用批量load/Store指令操作。一條批量指令可以實(shí)現(xiàn)在一組寄存器和一塊連續(xù)的內(nèi)存單元之間傳輸數(shù)據(jù)。一次最多傳輸16個(gè)內(nèi)存單元數(shù)據(jù)。指令中寄存器和內(nèi)存單元的對應(yīng)關(guān)系是,編號低的寄存器對應(yīng)于內(nèi)存中低地址單元。
格式為:LDM|STM{< cond >} < addressing_mode> < Rn >{!}, < registers >{^} < addressing_code>表示地址的變化方式,有以下四種:
- IA(increment After):事后遞增方式。第一個(gè)寄存器對應(yīng)的是內(nèi)存單元為基址寄存器< Rn >所指的單元內(nèi)存。隨后依次加4個(gè)字節(jié)
- IB(Increment Before):事先遞增方式。第一個(gè)寄存器對應(yīng)的是內(nèi)存單元為基址寄存器< Rn > + 4所指的單元內(nèi)存。隨后依次加4個(gè)字節(jié)
- DA(Decrement After):事后遞減方式。第一個(gè)寄存器對應(yīng)的是內(nèi)存單元為基址寄存器< Rn >- 4*(寄存器總個(gè)數(shù)-1)所指的單元內(nèi)存。隨后依次加4個(gè)字節(jié)
- DB(Decrement Before):事先遞減方式。第一個(gè)寄存器對應(yīng)的是內(nèi)存單元為基址寄存器< Rn >-4*(寄存器總個(gè)數(shù))所指的單元內(nèi)存。隨后依次加4個(gè)字節(jié)
對于通常的數(shù)據(jù)傳輸來說,由于load指令和store指令可以采用相同的尋址方式。但是對于數(shù)據(jù)棧的操作,數(shù)據(jù)寫入內(nèi)存和從內(nèi)存讀出的順序不同,所以使用的尋址方式也不一樣。棧尋址方式有:FD、ED、FA、EA4。
雜類load/store指令尋址方式
雜類指令包括操作數(shù)為半字、帶符號字節(jié)、雙字節(jié)的load/store指令。語法格式為:
LDR|STR{< cond >}H |SH|SB|D < Rd>,< addressing_mode>
- H:半字訪問。
- S:有符數(shù)據(jù)。
- B:字節(jié)數(shù)據(jù)訪問。
- W:雙字訪問。
這個(gè)尋址方式只有6種:尋址方法有普通偏移量、事先更新方法、事后更新方法。偏移量的格式有:立即數(shù)、寄存器。所以組合6種尋址方式: - [< Rn >,#+/-< offset_8>]
- [< Rn >,+/-< Rm >]
- [< Rn >,#+/-< offset_8>]!
- [< Rn >,+/-< Rm >]!
- [< Rn >],#+/-< offset_8>
- [< Rn >],+/-< Rm >
ARM指令集
跳轉(zhuǎn)指令
ARM中有兩種方式可以實(shí)現(xiàn)程序的跳轉(zhuǎn):使用跳轉(zhuǎn)指令、直接向PC中寫入目標(biāo)地址值。兩種的區(qū)別是直接操作PC寄存器,可以實(shí)現(xiàn)在4GB的地址空間任意跳轉(zhuǎn)(長跳轉(zhuǎn))。ARM的跳轉(zhuǎn)指令可以從當(dāng)前指令向前或向后32MB的地址空間跳轉(zhuǎn)。指令有B、BL、BLX、BX L將PC的值保存到LR寄存器中,X帶狀態(tài)切換的跳轉(zhuǎn)(可以切換到thumb指令集,目標(biāo)地址處的指令類型有目標(biāo)地址的bit[0]決定)。
數(shù)據(jù)處理指令
數(shù)據(jù)處理指令可以分為3類:數(shù)據(jù)傳送指令、算術(shù)邏輯運(yùn)算指令、比較指令。操作數(shù)的計(jì)算方法參考上述數(shù)據(jù)處理指令尋址方式部分。其中算術(shù)邏輯指令會(huì)將結(jié)果存入目標(biāo)寄存器,同時(shí)更新CPSR中的調(diào)價(jià)標(biāo)志位。而比較指令不保存運(yùn)算結(jié)果,只更新CPSR中相應(yīng)的條件標(biāo)志位。
-
數(shù)據(jù)傳輸指令有:MOV MVN
MOV|MVN {< cond >} {s} < Rd >, < shifter-operand >
MOV(MVN)指令是將< shifter_operand >表示的數(shù)據(jù)(的反碼)傳送到目標(biāo)寄存器< Rd>中。
note:MOVS PC,LR指令可以實(shí)現(xiàn)從某些異常中斷中返回。PC為目標(biāo)寄存器并且S位被設(shè)置,指令執(zhí)行時(shí)會(huì)將當(dāng)前處理器模式對應(yīng)的SPSR的值復(fù)制到CPSR中。 -
比較指令有:CMP CMN TST TEQ
< opcode > { < cond >} < Rn > ,< shifter_operand >
CMP指令是將< Rn >中的數(shù)值-< shifet_operand >的值,根據(jù)操作結(jié)果更新CPSR中相應(yīng)的條件標(biāo)志位。
CMN指令是將< Rn >中的數(shù)值+< shifet_operand >的值,根據(jù)操作結(jié)果更新CPSR中相應(yīng)的條件標(biāo)志位。
TST指令是將< Rn >中的數(shù)值與< shifet_operand >的值做按位與操作,根據(jù)操作結(jié)果更新CPSR中相應(yīng)的條件標(biāo)志位。
TEQ指令是將< Rn >中的數(shù)值與< shifet_operand >的值按位做異或操作,根據(jù)操作結(jié)果更新CPSR中相應(yīng)的條件標(biāo)志位。 -
算術(shù)邏輯指令有ADD SUB RSB ADC SBC RSC AND BIC EOR ORR
< opcode > {< cond >} {s} < Rd >, < Rn >, < shifter_operand >
ADD將操作數(shù)與寄存器< Rn >中的值相加,并把結(jié)果保存到目標(biāo)寄存器。
ADC帶位加法指令,在ADD的基礎(chǔ)上再加上CPSR中的C條件標(biāo)志位的值。
eg:64位操作數(shù)相加。R0和R1中放置一個(gè)64位的源操作數(shù),R0中放置低33位,R2和R3中也是一個(gè)64位的源操作數(shù),R2中存放低32位
ADDS R4,R0,R2
ADC R5 , R1,R3 ==>R5R4就是計(jì)算出來的結(jié)果
SUB、SUC減法指令和帶位減法指令。SUC在SUB的基礎(chǔ)上再減去CPSR中C條件標(biāo)志位的反碼。這兩個(gè)指令聯(lián)合使用同樣也可以進(jìn)行64位數(shù)的減法操作。
SUBS R4,R0,R2
SUC R5,R1,R3
RSB、RSC逆向減法指令以及帶位逆向減法指令。 < Rd> = < shifter_operand> - < Rn >
乘法指令:(這個(gè)使用的不多)
- MUL:32位乘法指令。
- MLA:32位帶加數(shù)的乘法指令。
- SMULL:64位有符號數(shù)乘法指令。
- SMLAL:64位帶加數(shù)的有符號數(shù)乘法指令。
- UMULL:64位無符號數(shù)乘法指令。
- UMLAL: 64位帶加數(shù)的無符號數(shù)乘法指令。
CLZ {< cond >} < Rd >, < Rm >。指令用于計(jì)算寄存器中操作數(shù)最高端0的個(gè)數(shù)。
ARM指令集中的除法運(yùn)算是通過協(xié)處理器來實(shí)現(xiàn)的,所以沒有除法算術(shù)的指令。
AND、ORR、EOR、BIC分別是按位邏輯與、或、異或、清除操作。
程序狀態(tài)寄存器傳輸指令
ARM中有兩條指令用于在狀態(tài)寄存器和通用寄存器之間傳送數(shù)據(jù)。程序不能通過直接修改CPSR中的T控制位直接將程序狀態(tài)切換到thumb狀態(tài),必須通過BX等指令完成程序狀態(tài)的切換。通常程序狀態(tài)寄存器修改是通過“讀->改->寫”的方式來實(shí)現(xiàn)的。
- MSR 通用寄存器到狀態(tài)寄存器的傳送指令。即寫入。
- MRS 狀態(tài)寄存器到通用寄存器的傳送指令。即讀取。
Load/Store指令
load指令用于從內(nèi)存中讀取數(shù)據(jù)放入到寄存器中,store指令用于將寄存器中的數(shù)據(jù)保存到內(nèi)存中。
對于大量搬移數(shù)據(jù),ARM還提供了批量Load/Store內(nèi)存訪問指令。批量load指令可以一次性從連續(xù)的內(nèi)存單元中讀取數(shù)據(jù),傳送到寄存器中。而批量store指令則是異性性將寄存器列表中的多個(gè)寄存器值寫入到內(nèi)存中。
LDM|STM {< cond >} < addressing_mode > Rn{!} , < registers >{^}
命令中的**!**指令執(zhí)行操作后會(huì)將操作數(shù)的內(nèi)存地址寫入基址寄存器< Rn >中,即更新基地址。
^ 表示指令執(zhí)行時(shí)將當(dāng)前處理器模式下的SPSR值復(fù)制到CPSR中。寄存器中不包含PC時(shí),作用指示指令中所用的寄存器為用戶模式下的寄存器。
在數(shù)據(jù)傳送指令中有一條比較特殊的指令。對于信號量的操作要求是一個(gè)原子操作(不能被中斷,即只有一條指令)。SWP指令完成讀取和修改寄存器的時(shí),所以用于信號量的操作。
swp {< cond >} < Rd > ,< Rm >, [< Rn >] 執(zhí)行的結(jié)果是把Rn的內(nèi)容讀取到Rd中,同時(shí)將Rm寄存器的內(nèi)容寫入到Rn中。
協(xié)處理器指令
ARM協(xié)處理器指令包括以下3類:
- 用于ARM處理器初始化ARM協(xié)處理器的數(shù)據(jù)處理操作。CDP
- 用于ARM處理器的寄存器和ARM協(xié)處理器的寄存器間的數(shù)據(jù)傳送操作。MCR、MRC
- 用于在ARM協(xié)處理器的寄存器和內(nèi)存單元之間傳送數(shù)據(jù)。LDC、STC
CDP協(xié)處理器操作指令。CDP指令讓ARM處理器能夠通知ARM協(xié)處理器執(zhí)行特定的操作,該操作由協(xié)處理器完成。
LDC指令從連續(xù)的內(nèi)存單元將數(shù)據(jù)讀取到協(xié)處理器的寄存器中。而STC指令將協(xié)處理器的寄存器中的數(shù)據(jù)寫入到一系列的內(nèi)存單元中。
格式:
LDC { < cond >} {L} < coproc > , < CRd > ,< addressing_mode >
LDC2 { L } < coproc >, < CRd >, < addressing_mode >
STC {< cond >} {L} < coproc > , < CRd > ,< addressing_mode >
STC2 { L } < coproc >, < CRd >, < addressing_mode >
MCR指令將ARM處理器的寄存器中的數(shù)據(jù)傳送到協(xié)處理器的寄存器中,而MRC則是將協(xié)處理器寄存器中的數(shù)值傳送到ARM處理器的寄存器中。
MCR {< cond >} < coproc > ,< opcode_1>, < Rd >, < CRn > , < CRm > {,< opcode2 >}
MCR2 < coproc > ,< opcode_1>, < Rd >, < CRn > , < CRm > {,< opcode2 >}
MRC {< cond >} < coproc > ,< opcode_1>, < Rd >, < CRn > , < CRm > {,< opcode2 >}
MRC2 < coproc > ,< opcode_1>, < Rd >, < CRn > , < CRm > {,< opcode2 >}
< Rd >:為ARM寄存器,其值將被傳送到協(xié)助利器的寄存器中或者是從協(xié)助處理寄存器中讀取數(shù)值。
< CRn >:為協(xié)助處理器寄存器
< CRm >:為附加的目標(biāo)寄存器或者源操作數(shù)寄存器。
異常中斷產(chǎn)生指令
在ARM概述中,咱們知道ARM有7種模式,可以分為用戶模式和特權(quán)模式。在特權(quán)模式中可以訪問系統(tǒng)的所有資源以及任意切換到別的模式。但是在用戶模式中,權(quán)限就沒有這么大,那么用戶模式下要訪問系統(tǒng)的資源怎么辦呢?ARM提供了異常中斷指令SWI,通過軟中斷實(shí)現(xiàn)在用戶模式中對操作系統(tǒng)中特權(quán)模式的程序的調(diào)用。
SWI {< cond >} < immed_24 > 操作系統(tǒng)通過24位的立即數(shù)來區(qū)分用戶程序請求的服務(wù)類型。
ARM中的指令執(zhí)行條件碼如下:
??
立即數(shù)是32bit,但是并不是所有的操作數(shù)都是立即數(shù)。立即數(shù)=8位數(shù)據(jù)>>偶數(shù)陪(最多是移位30位,有些地方說是32位,右移32位其實(shí)就是沒有移位),立即數(shù)的構(gòu)成是使用移位最少的那個(gè)方式,所以數(shù)據(jù)寬度超多了8bit肯定就不是立即數(shù)了。在ARM指令集中立即數(shù)使用#標(biāo)記。 ??
算術(shù)右移是帶有符號位,即最高位的值保留;邏輯右移是用0填充左邊被移走的位;循環(huán)右移是用右邊移出的位填充左邊的位;帶拓展的循環(huán)右移是使用CPSR中的C位填充最高位。 ??
F(full)、E(empty):棧指針指向棧頂元素(最后一個(gè)入棧的數(shù)據(jù))時(shí)稱為full棧,棧指針指向與棧頂元素相鄰的一個(gè)可用數(shù)據(jù)單元時(shí)稱為empty棧。D(descending):數(shù)據(jù)棧向內(nèi)存地址減少的方向增長,A(ascending)數(shù)據(jù)棧向內(nèi)存地址增加的方向增長。 ??
總結(jié)
- 上一篇: 老王带你理解算法复杂度O(1),O(N)
- 下一篇: MIK C语言面试两题