ARM指令集(下)
A.2.5?? ARM 協處理器指令
??????? ARM 支持協處理器操作,協處理器的控制要通過協處理器命令實現。表A-7給出全部的ARM協處理器指令。
??????? CDP
??????? 協處理器數據操作指令。ARM 處理器通過CDP 指令通知ARM 協處理器執行特定的操作。該操作由協處理器完成,即對命令的參數的解釋與協處理器有關,指令的使用取決于協處理器。若協處理器不能成功地執行該操作,將產 生未定義指令異常中斷。指令格式如下:
??????? CDP{cond} coproc,opcodel,CRd,CRn,CRm{,opcode2}
??????? 其中: coproc 指令操作的協處理器名。標準名為pn,n 為0~15。
??????? opcodel 協處理器的特定操作碼。
??????? CRd 作為目標寄存器的協處理器寄存器。
??????? CRN 存放第1 個操作數的協處理器寄存器。
??????? CRm 存放第2 個操作數的協處理器寄存器。
??????? Opcode2 可選的協處理器特定操作碼。
??????? CDP 指令舉例如下:
??????? CDP p7,0,c0,c2,c3,0 ;協處理器7 操作,操作碼為0,可選操作碼為0
??????? CDP p6,1,c3,c4,c5 ;協處理器操作,操作碼為1
??????? LDC
??????? 協處理器數據讀取指令。LDC 指令從某一連續的內存單元將數據讀取到協處理器的寄存器中。協處理器數據的數據的傳送,由協處理器來控傳送的字數。若協處理器不能成功地執行該操作,將產生未定義指令異常中斷。指令格式如下:
??????? LDC{cond}{L} coproc,CRd,<地址>
??????? 其中: L 可選后綴,指明是長整數傳送。
??????? coproc 指令操作的協處理器名。標準名為pn,n 為0~15
??????? CRd 作為目標寄存的協處理器寄存器。
??????? <地址> 指定的內存地址
??????? LDC 指令舉例如下:
??????? LDC p5,c2,[R2,#4];讀取R2+4指向的內存單元的數據,傳送到協處理器p5的c2寄存器中
??????? LDC p6,c2,[R1] ;讀取是指向的內存單元的數據,傳送到協處理器p6 的c2 寄存器中
??????? STC
??????? 協處理器數據寫入指令。STC 指令將協處理器的寄存器數據寫入到某一連續的內存單元中。進行協處理器數據的數據傳送,由協處理器來控制傳送的字數。若協處理器不能成功地執行該操作,將產生未定義指令異常中斷。指令格式如下:
??????? STC{cond}{L} coproc,CRd,<地址>
??????? 其中: L 可選后綴,指明是長整數傳送。
??????? coproc 指令操作的協處理器名。標準名為pn,n 為0~15
??????? CRd 作為目標寄存的協處理器寄存器。
??????? <地址> 指定的內存地址
??????? STC 指令舉例如下:
??????? STC p5,c1,[R0]
??????? STC p5,c1,[Ro,#-0x04]
??????? MCR
??????? ARM 寄存器到協處理器寄存器的數據傳送指令。MCR 指令將ARM 處理器的寄存器中的數據傳送到協處理器的寄存器中。若協處理器不能成功地執行該操作,將產生未定義指令異常中斷。指令格式如下:
??????? MCR{cond} coproc,opcodel,Rd,CRn,CRm{,opcode2}
??????? 其中:coproc 指令操作的協處理器名。標準名為pn,n 為0~15。
??????? cpcodel 協處理器的特定操作碼。
??????? CRD 作為目標寄存器的協處理器寄存器。
??????? CRn 存放第1 個操作數的協處理器寄存器
??????? CRm 存放第2 個操作數的協處理器寄存器。
??????? Opcode2 可選的協處理器特定操作碼。
??????? MCR 指令舉例如下:
??????? MCR p6,2,R7,c1,c2,
??????? MCR P7,0,R1,c3,c2,1,
??????? MRC
??????? 協處理器寄存器到ARM 寄存器到的數據傳送指令。MRC 指令將協處理器寄存器中的數據傳送到ARM 處理器的寄存器中。若協處理器不能成功地執行該操作。將產生未定義異常中斷。指令格式如下:
??????? MRC {cond} coproc,opcodel,Rd,CRn,CRm{,opcode2}
??????? 其中:coproc 指令操作的協處理器名。標準名為pn,n為0~15。
??????? opcodel 協處理器的特定操作碼。
??????? CRd 作為目標寄存器的協處理器寄存器。
??????? CRn 存放第1 個操作數的協處理器寄存器。
??????? CRm 存放第2 個操作數的協處理器寄存器。
??????? opcode2 可選的協處理器特定操作碼。
??????? MRC 指令舉例如下:
??????? MRC p5,2,R2,c3,c2
??????? MRC p7,0,R0,c1,c2,1
A.2.6?? ARM 雜項指令
??????? 表A-8給出全部的ARM協處理器指令。
??????? SWI
??????? 軟中斷指令。SWI 指令用于產生軟中斷,從而實現在用戶模式變換到管理模式,CPSR保存到管理模式的SPSR 中,執行轉移到SWI 向量,在其它模式下也可使用SWI 指令,處理同樣地切換到管理模式。指令格式如下:
??????? SWI{cond} immed_24
??????? 其中:immed_24 24 位立即數,值為0~16777215 之間的整數。
??????? SWI 指令舉例如下:
??????? SWI 0 ;軟中斷,中斷立即數為0
??????? SWI 0x123456 ;軟中斷,中斷立即數為0x123456
??????? 使用SWI 指令時,通常使用以下兩種方法進行傳遞參數,SWI 異常中斷處理程序就可以提供相關的服務,這兩種方法均是用戶軟件協定。SWI 異常中斷處理程序要通過讀取引起軟中斷的SWI 指令,以取得24 位立即數。
??????? (A)指令24 位的立即數指定了用戶請求的服務類型,參數通過用寄存器傳遞。
??????? MOV R0,#34 ??? ;設置了功能號為34
??????? SWI 12 ??? ??? ;調用12 號軟中斷
??????? (B)指令中的24 位立即數被忽略,用戶請求的服務類型由寄存器R0 的值決定,參數通過其它的通用寄存器傳遞。
??????? MOV R0,#12 ??? ;調用12 號軟中斷
??????? MOV R1,#34 ??? ;設置子功能號為34
??????? SWI 0??? ??? ;
??????? 在SWI 異常中斷處理程序中,取出SWI 立即數的步驟為:首先確定引起軟中斷的SWI指令是ARM 指令還時Thumb 指令,這可通過對SPSR 訪問得到:然后要取得該SWI 指令的地址,這可通過訪問LR 寄存器得到:接著讀出指令,分解出立即數。
??????? 讀出SWI 立即數:
??????? T_bit EQU 0x20
??????? SWI_Hander
??????? STMFD SP!,{R0_R3,R12,LR} ??? ??? ;現場保護
??????? MRS R0,SPSR ??? ??? ??? ??? ??? ;讀取SPSR
??????? STMFD SP!,{R0} ??? ??? ??? ??? ??? ;保存SPSR
??????? TST R0,#T_bit ??? ??? ??? ??? ??? ;測試T 標志位
??????? LDRNEH R0,[LR,#-2] ??? ??? ??? ??? ;若是Thumb 指令,讀取指令碼(16 位)
??????? BICNE R0,R0,#0xFF00 ??? ??? ??? ;取得Thumb 指令的8 位立即數
??????? LDREQ R0,[LR,#-4] ??? ??? ??? ??? ;若是ARM 指令,讀取指令碼(32 位)
??????? BICNQ R0,R0,#0xFF00000 ??? ??? ??? ;取得ARM 指令的24 位立即數
??????? …
??????? LDMFD SP!,{R0-R3,R12,PC}^ ;SWI 異常中斷返回
??????? MRS
??????? 讀狀態寄存器指令。在ARM 處理器中,只有MRS 指令可以狀態寄存器CPSR 或SPSR讀出到通用寄存器中。指令格式如下:
??????? MRS{cond} Rd ,psr
??????? 其中: Rd 目標寄存器。Rd 不允許為R15。
??????? psr CPSR 或SPSR
??????? MRS指令舉例如下:
??????? MRS R1,CPSR ??? ;將CPSR 狀態寄存器讀取,保存到R1 中
??????? MRS R2,SPSR ??? ;將SPSR 狀態寄存器讀取,保存到R2 中
??????? MRS 指令讀取CPSR,可用來判斷ALU 的狀態標志,或IRQ、FIQ 中斷是否允許等;在異常處理程序中,讀SPSR 可知道進行異常前的處理器狀態等。MRS 與MSR 配合使用,實現CPSR 或SPSR 寄存器的讀—修改---寫操作,可用來進行處理器模式切換(),允許/禁止IRQ/FIQ 中斷等設置。另外,進程切換或允許異常中斷嵌套時,也需要使用MRS 指令讀取SPSR 狀態值。保存起來。
??????? 使能IRQ 中斷例程:
??????? ENABLE_IRQ
??????? MRS R0,CPSR
??????? BIC R0。R0,#0x80
??????? MSR CPSR_c,R0
??????? MOV PC,LR
??????? 禁能IRQ 中斷例程:
??????? DISABLE_IRQ
??????? MRS R0,CPSR
??????? ORR R0,R0,#0x80
??????? MSR CPSR_c,R0
??????? MOV PC,LR
??????? MSR
??????? 寫狀態寄存器指令。在ARM 處理器中。只有MSR 指令可以直接設置狀態寄存器CPSR或SPSR。指令格式如下:
??????? MSR{cond} psr_fields,#immed_8r
??????? MSR{cond} psr_fields,Rm
??????? 其中: psr CPSR 或SPSR
??????? fields 指定傳送的區域。Fields 可以是以下的一種或多種(字母必須為小寫):
??????? c 控制域屏蔽字節(psr[7…0])
??????? x 擴展域屏蔽字節(psr[15…8])
??????? s 狀態域屏蔽字節(psr[23?!?6])
??????? f 標志域屏蔽字節(psr[31…24])
??????? immed_8r 要傳送到狀態寄存器指定域的立即數,8 位。
??????? Rm 要傳送到狀態寄存器指定域的數據的源寄存器。
??????? MSR 指令舉例如下:
??????? MSR CPSR_c,#0xD3 ;CPSR[7…0]=0xD3,即切換到管理模式。
??????? MSR CPSR_cxsf,R3 ;CPSR=R3
??????? 只有在特權模式下才能修改狀態寄存器。
??????? 程序中不能通過MSR 指令直接修改CPSR 中的T 控制位來實現ARM 狀態/Thumb 狀態的切換,必須使用BX 指令完成處理器狀態的切換(因為BX 指令屬轉移指令,它會打斷流水線狀態,實現處理器狀態切換)。MRS 與MSR 配合使用,實現CPSR 或SPSR 寄存器的讀-修改-寫操作,可用來進行處理器模式切換、允許/禁止IRQ/FIQ 中斷等設置。
??????? 堆棧指令實始化例程:
??????? INITSTACK
??????? MOV R0,LR ;保存返回地址
??????? ;設置管理模式堆棧
??????? MSR CPSR_c,#0xD3
??????? LDR SP,StackSvc
?????????????????????? ;設置中斷模式堆棧
??????? MSR CPSR_c,#0xD2
??????? LDR SP,StackIrq
??????? …
A.2.7?? ARM 偽指令
??????? ARM 偽指令不是ARM 指令集中的指令,只是為了編程方便編譯器定義了偽指令,使用時可以像其它ARM 指令一樣使用,但在編譯時這些指令將被等效的ARM 指令代替。ARM 偽指令有四條,分別為ADR 偽指令、ADRL 偽指令、LDR 偽指令和NOP 偽指令。
??????? ADR
??????? 小范圍的地址讀取偽指令。ADR 指令將基于PC 相對偏移的地址值讀取到寄存器中。在匯編編譯源程序時,ADR 偽指令被編譯器替換成一條合適的指令。通常,編譯器用一條ADD 指令或SUB 指令來實現該ADR 偽指令的功能,若不能用一條指令實現,則產生錯誤,編譯失敗。
??????? ADR 偽指令格式如下:
??????? ADR{cond} register,exper
??????? 其中:register 加載的目標寄存器。
??????? exper 地址表達式。當地址值是非字地齊時,取值范圍-255~255 字節之間;當地址是字對齊時,取值范圍-1020~1020 字節之間。
??????? 對于基于PC 相對偏移的地址值時,給定范圍是相對當前指令地址后兩個字處(因為ARM7TDMI 為三級流水線)。
??????? ADR 偽指令舉例如下:
??????? LOOP MOV R1, #0xF0
??????? …
??????? ADR R2, LOOP ??? ??? ;將LOOP 的地址放入R2
??????? ADR R3, LOOP+4
??????? 可以用ADR 加載地址,實現查表:
??????? …
??????? ADR R0,DISP_TAB ??? ;加載轉換表地址
??????? LDRB R1,[R0,R2] ??? ;使用R2 作為參數,進行查表
??????? …
??????? DISP_TAB
??????? DCB 0Xc0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90
??????? ADRL
??????? 中等范圍的地址讀取偽指令。ADRL 指令將基于PC 相對偏移的地址值或基于寄存器相對偏移的地址值讀取到寄存器中,比ADR 偽指令可以讀取更大范圍的地址。在匯編編譯源程序時,ADRL 偽指令被編譯器替換成兩個條合適的指令。若不能用兩條指令實現ADRL 偽指令功能,則產生錯誤,編譯失敗。ADRL 偽指令格式如下:
??????? ADR{cond} register,exper
??????? 其中:register 加載的目標寄存器。
??????? expr 地址表達式。當地址值是非字對齊時,取范圍-64K~64K 字節之間;當地址值是字對齊時,取值范圍-256K~256K 字節之間。
??????? ADRL 偽指令舉例如下:
??????? ADRL R0,DATA_BUF
??????? …
??????? ADRL R1 DATA_BUF+80
??????? …
??????? DATA_BUF
??????? SPACE 100 ??? ;定義100 字節緩沖區
??????? 可以且用ADRL 加載地址,實現程序跳轉,中等范圍地址的加載:
??????? …
??????? ADR LR,RETURNI ??? ??? ??? ;設置返回地址
??????? ADRL R1 Thumb_Sub+1??? ??? ;取得了Thumb 子程序入口地址,且R1 的0 位置1
??????? BX R1 ??? ??? ??? ??? ??? ;調用Thumb 子程序,并切換處理器狀態
??????? RETURNI
??????? …
??????? CODE16
??????? Thumb_Sub
??????? MOV R1,#10
??????? …
??????? LDR
??????? 大范圍的地址讀取偽指令。LDR 偽指令用于加載32 位的立即數或一個地址值到指定寄存器。在匯編編譯源程序時,LDR 偽指令被編譯器替換成一條合適的指令。若加載的常數未超出MOV 或MVN 的范圍,則使用MOV 或MVN 指令代替該LDR 偽指令,否則匯編器將常量放入字池,并使用一條程序相對偏移的LDR 指令從文字池讀出常量。LDR 偽指令格式如下:
??????? LDR{cond} register,=expr/label_expr
??????? 其中:register 加載的目標寄存器
??????? expr 32 位立即數。
??????? label_expr 基于PC 的地址表達式或外部表達式。
??????? LADR 偽指令舉例如下:。
??????? LDR R0,=0x123456 ??? ??? ;加載32 位立即數0x12345678
??????? LDR R0,=DATA_BUF+60 ??? ;加載DATA_BUF 地址+60
??????? …
??????? LTORG ??? ??? ??? ??? ??? ;聲明文字池
??????? 偽指令LDR 常用于加載芯片外圍功能部件的寄存器地址(32 位立即數),以實現各種控制操作加載32 位立即數:
??????? …
??????? LDR R0,=IOPIN ;加載GPIO 寄存器IOPIN 的地址
??????? LDR R1,[R0] ;讀取IOPIN 寄存器的值
??????? …
??????? LDR R0,=IOSET
??????? LDR R1,=0x00500500
??????? STR R1,[R0] ;IOSET=0x00500500
??????? …
??????? 從PC 到文字池的偏移量必須小于4KB。與ARM 指令的LDR 相比,偽指令的LDR 的參數有“=”號
??????? NOP
??????? 空操作偽指令。NOP 偽指令在匯編時將會被代替成ARM 中的空操作,比如可能為“MOV? R0, R0”指令等,NOP 偽指令格式如下:
??????? NOP
??????? NOP
??????? NOP
??????? NOP
??????? SUBS R1, R1, #1
??????? BNE DELAY1
??????? …
轉載于:https://www.cnblogs.com/getyoulove/p/3672034.html
總結
- 上一篇: 超短的判断IE javascript代码
- 下一篇: 好久没有写了,今天就谈谈微信吧!