ARM指令集【 PUSH \POP】【跳轉B\BL\BX\BLX \BXJ】【數據操作LDR\LDRB\LDRH\LDM\STR\STRB\STRH\STM】【移位LSL/LSR/ASL/ASR】

官方文檔指令集概述:
在這裏插入圖片描述
具體的指令集介紹:
在這裏插入圖片描述

PUSH and POP

本博客摘錄於:http://blog.sina.com.cn/s/blog_95baef7b01014ub4.html
示例 :
PUSH {R4,LR}
將低寄存器R4入棧,LR也入棧。
POP {R4,PC}
將堆棧中的數據彈出到低寄存器 R4 及 PC 中
說明 :
寄存器入棧及出棧指令.實現低寄存器和可選的 LR 寄存器入棧寄存器和可選的 PC寄存器出棧操作,堆棧地 址由 SP 寄存設置,堆棧是滿遞減堆棧.指令格式如下;
PUSH {reglist[,LR]}
POP {reglist[,PC]}
其中 reglist 入棧/出棧低寄存器列表,即 R0~R7
LR 入棧時的可選寄存器
PC 出棧時的可選寄存器
寄存器入棧及出棧指令舉例如下;
PUSH {R0-R7,LR} ;將低寄存器 R0~R7 全部入棧,LR 也入棧
POP {R0-R7,PC} ;將堆棧中的數據彈出到低寄存器 R0~R7 及 PC 中
滿遞減堆棧 含義可參照如下:
堆棧尋址
堆棧是特定順序進行存取的存儲區,操作順序分爲“後進先出”和“先進後出”
堆棧尋址時隱含的,它使用一個專門的寄存器(堆棧指針)指向一塊存儲區域(堆棧),
指針所指向的存儲單元就是堆棧的棧頂。存儲器堆棧可分爲兩種:
向上生長:向高地址方向生長,稱爲遞增堆棧
向下生長:向低地址方向生長,稱爲遞減堆棧
堆棧指針指向最後壓入的堆棧的有效數據項,
稱爲滿堆棧;
堆棧指針指向下一個要
放入的空位置,
稱爲空堆棧。
這樣就有 4 中類型的堆棧表示遞增和遞減的滿堆棧和空堆棧的各種組合。

  1. 滿遞增:堆棧通過增大存儲器的地址向上增長,堆棧指針指向內含有效數據項的最高地址。
    指令如 LDMFA,STMFA 等。
  2. 空遞增:堆棧通過增大存儲器的地址向上增長,堆棧指針指向堆棧上的第一個空位置。
    指令如 LDMEA,STMEA 等。
  3. 滿遞減:
    堆棧通過減小存儲器的地址向下增長,堆棧指針指向內含有效數據項的最低地址。
    指令如 LDMFD,STMFD 等。
  4. 空遞減:堆棧通過減小存儲器的地址向下增長,堆棧指針指向堆棧下的第一個空位置。
    指令如 LDMED,STMED 等。
    堆棧尋址指令舉例如下:
    STMFD SP!,{R1-R7,LR} ; 將 R1~R7,LR 入棧。滿遞減堆棧。
    LDMFD SP!,{R1-R7,LR} ;數據出棧,放入 R1~R7,LR 寄存器。滿遞減堆棧。

彙編跳轉指令B、BL、BX、BLX 和 BXJ

本文摘錄於:https://blog.csdn.net/bytxl/article/details/49883103
跳轉指令用於實現程序流程的跳轉,在 ARM 程序中有兩種方法可以實現程序流程的跳轉:
(1) 使用專門的跳轉指令。
(2) 直接向程序計數器 PC 寫入跳轉地址值。
通過向程序計數器 PC 寫入跳轉地址值,可以實現在 4GB 的地址空間中的任意跳轉,在跳轉之前結合使用
MOV LR , PC
等類似指令,可以保存下一條指令地址作爲將來的返回地址值,從而實現在 4GB 連續的線性地址空間的子程序調用。
專門的跳轉指令
B、BL、BX、BLX 和 BXJ:
跳轉、帶鏈接跳轉(帶返回的跳轉)、跳轉並切換指令集、帶鏈接跳轉並切換指令集(帶返回的跳轉並切換指令集)、跳轉並轉換到 Jazelle 狀態。
1、 B 指令
B 指令的格式爲:
B{條件} 目標地址
B 指令是最簡單的跳轉指令。一旦遇到一個 B 指令,ARM 處理器將立即跳轉到給定的目標地址,從那裏繼續執行。注意:B指令是不會把當前指針存放到R14寄存器的,注意存儲在跳轉指令中的實際值是相對當前PC 值的一個偏移量,而不是一個絕對地址,它的值由彙編器來計算(參考尋址方式中的相對尋址)。它是 24 位有符號數,左移兩位後有符號擴展爲 32 位,表示的有效偏移爲 26 位(前後32MB 的地址空間)。以下指令:
B Label ;程序無條件跳轉到標號 Label 處執行
CMP R1 ,# 0 ;當 CPSR 寄存器中的 Z 條件碼置位時,程序跳轉到標號 Label 處執行
BEQ Label
2、 BL 指令
BL 指令的格式爲:
BL{條件} 目標地址
BL 是另一個跳轉指令,但跳轉之前,會在寄存器R14 中保存PC 的當前內容,因此,可以通過將R14 的內容重新加載到PC 中,來返回到跳轉指令之後的那個指令處執行。該指令是實現子程序調用的一個基本但常用的手段。以下指令:
BL Label ;當程序無條件跳轉到標號 Label 處執行時,同時將當前的 PC 值保存到 R14 中
3、 BLX 指令
BLX 指令的格式爲:
BLX 目標地址
BLX 指令從ARM 指令集跳轉到指令中所指定的目標地址,並將處理器的工作狀態有ARM 狀態切換到Thumb 狀態,該指令同時將PC 的當前內容保存到寄存器R14 中。因此,當子程序使用Thumb 指令集,而調用者使用ARM 指令集時,可以通過BLX 指令實現子程序的調用和處理器工作狀態的切換。
同時,子程序的返回可以通過將寄存器R14 值複製到PC 中來完成。
4、 BX 指令
BX 指令的格式爲:
BX{條件} 目標地址
BX 指令跳轉到指令中所指定的目標地址,目標地址處的指令既可以是ARM 指令,也可以是Thumb指令。
總結
語法
op1{cond}{.W} label

op2{cond} Rm
其中:
op1
是下列項之一:
B
跳轉。
BL
帶鏈接跳轉
BLX
帶鏈接跳轉並切換指令集。
op2
是下列項之一:
BX
跳轉並切換指令集。
BLX
帶鏈接跳轉並切換指令集。
BXJ
跳轉並轉換爲 Jazelle 執行。
cond
是一個可選的條件代碼。 cond 不能用於此指令的所有形式。
.W
是一個可選的指令寬度說明符,用於強制要求在 Thumb-2 中使用 32 位 B 指令。
label
是一個程序相對的表達式。
Rm
是一個寄存器,包含要跳轉到的目標地址。
操作
所有這些指令均會引發跳轉,或跳轉到 label,或跳轉到包含在 Rm 中的地址處。 此外:
BL 和 BLX 指令可將下一個指令的地址複製到 lr(r14,鏈接寄存器)中。
BX 和 BLX 指令可將處理器的狀態從 ARM 更改爲 Thumb,或從 Thumb 更改爲 ARM。
BLX label 無論何種情況,始終會更改處理器的狀態。
BX Rm 和 BLX Rm 可從 Rm 的位 [0] 推算出目標狀態:
如果 Rm 的位 [0] 爲 0,則處理器的狀態會更改爲(或保持在)ARM 狀態
如果 Rm 的位 [0] 爲 1,則處理器的狀態會更改爲(或保持在)Thumb 狀態。
BXJ 指令會將處理器的狀態更改爲 Jazelle
http://www.techbulo.com/535.html
http://luleimi.blog.163.com/blog/static/175219645201210922139272/

**

ARM的六大類指令集—LDR、LDRB、LDRH、STR、STRB、STRH

**
本文摘錄於:https://blog.csdn.net/u013477200/article/details/50723555

ARM微處理器支持加載/存儲指令用於在寄存器和存儲器之間傳送數據,加載指令用於將存儲器中的數據傳送到寄存器,存儲指令則完成相反的操作。常用的加載存儲指令如下:

— LDR 字數據加載指令

— LDRB 字節數據加載指令

— LDRH 半字數據加載指令

— STR 字數據存儲指令

— STRB 字節數據存儲指令

— STRH 半字數據存儲指令
1、LDR指令

LDR指令的格式爲:

LDR{條件} 目的寄存器,<存儲器地址>

LDR指令用於從存儲器中將一個32位的字數據傳送到目的寄存器中。該指令通常用於從存儲器中讀取32位的字數據到通用寄存器,然後對數據進行處理。當程序計數器PC作爲目的寄存器時,指令從存儲器中讀取的字數據被當作目的地址,從而可以實現程序流程的跳轉。該指令在程序設計中比較常用,且尋址方式靈活多樣,請讀者認真掌握。

指令示例:

LDR R0,[R1] ;將存儲器地址爲R1的字數據讀入寄存器R0。

LDR R0,[R1,R2] ;將存儲器地址爲R1+R2的字數據讀入寄存器R0。

LDR R0,[R1,#8] ;將存儲器地址爲R1+8的字數據讀入寄存器R0。

LDR R0,[R1,R2] ! ;將存儲器地址爲R1+R2的字數據讀入寄存器R0,並將新地址R1+R2寫入R1。

LDR R0,[R1,#8] ! ;將存儲器地址爲R1+8的字數據讀入寄存器R0,並將新地址R1+8寫入R1。

LDR R0,[R1],R2 ;將存儲器地址爲R1的字數據讀入寄存器R0,並將新地址R1+R2寫入R1。

LDR R0,[R1,R2,LSL#2]! ;將存儲器地址爲R1+R2×4的字數據讀入寄存器R0,並將新地址R1+R2×4寫入R1。

LDR R0,[R1],R2,LSL#2 ;將存儲器地址爲R1的字數據讀入寄存器R0,並將新地址R1+R2×4寫入R1。
2、LDRB指令

LDRB指令的格式爲:

LDR{條件}B 目的寄存器,<存儲器地址>

LDRB指令用於從存儲器中將一個8位的字節數據傳送到目的寄存器中,同時將寄存器的高24位清零。該指令通常用於從存儲器中讀取8位的字節數據到通用寄存器,然後對數據進行處理。當程序計數器PC作爲目的寄存器時,指令從存儲器中讀取的字數據被當作目的地址,從而可以實現程序流程的跳轉。

指令示例:

LDRB R0,[R1] ;將存儲器地址爲R1的字節數據讀入寄存器R0,並將R0的高24位清零。

LDRB R0,[R1,#8] ;將存儲器地址爲R1+8的字節數據讀入寄存器R0,並將R0的高24位清零。
3、LDRH指令

LDRH指令的格式爲:

LDR{條件}H 目的寄存器,<存儲器地址>

LDRH指令用於從存儲器中將一個16位的半字數據傳送到目的寄存器中,同時將寄存器的高16位清零。該指令通常用於從存儲器中讀取16位的半字數據到通用寄存器,然後對數據進行處理。當程序計數器PC作爲目的寄存器時,指令從存儲器中讀取的字數據被當作目的地址,從而可以實現程序流程的跳轉。

指令示例:

LDRH R0,[R1] ;將存儲器地址爲R1的半字數據讀入寄存器R0,並將R0的高16位清零。

LDRH R0,[R1,#8] ;將存儲器地址爲R1+8的半字數據讀入寄存器R0,並將R0的高16位清零。

LDRH R0,[R1,R2] ;將存儲器地址爲R1+R2的半字數據讀入寄存器R0,並將R0的高16位清零。

4、LDM指令:

L的含義仍然是LOAD,即是Load from memory into register。

雖然貌似是LDR的升級,但是,千萬要注意,這個指令運行的方向和LDR是不一樣的,是從左到右運行的。該指令是將內存中堆棧內的數據,批量的賦值給寄存器,即是出棧操作;其中堆棧指針一般對應於SP,注意SP是寄存器R13,實際用到的卻是R13中的內存地址,只是該指令沒有寫爲[R13],同時,LDM指令中寄存器和內存地址的位置相對於前面兩條指令改變了,下面的例子:

LDMFD SP! , {R0, R1, R2}

實際上可以理解爲: LDMFD [SP]!, {R0, R1, R2}

意思爲:把sp指向的3個連續地址段(應該是3*4=12字節(因爲爲r0,r1,r2都是32位))中的數據拷貝到r0,r1,r2這3個寄存器中去。

5、STR指令

STR指令的格式爲:

STR{條件} 源寄存器,<存儲器地址>

STR指令用於從源寄存器中將一個32位的字數據傳送到存儲器中。該指令在程序設計中比較常用,且尋址方式靈活多樣,使用方式可參考指令LDR。

指令示例:

STR R0,[R1],#8 ;將R0中的字數據寫入以R1爲地址的存儲器中,並將新地址R1+8寫入R1。

STR R0,[R1,#8] ;將R0中的字數據寫入以R1+8爲地址的存儲器中。
6、STRB指令

STRB指令的格式爲:

STR{條件}B 源寄存器,<存儲器地址>

STRB指令用於從源寄存器中將一個8位的字節數據傳送到存儲器中。該字節數據爲源寄存器中的低8位。

指令示例:

STRB R0,[R1] ;將寄存器R0中的字節數據寫入以R1爲地址的存儲器中。

STRB R0,[R1,#8] ;將寄存器R0中的字節數據寫入以R1+8爲地址的存儲器中。
7、STRH指令

STRH指令的格式爲:

STR{條件}H 源寄存器,<存儲器地址>

STRH指令用於從源寄存器中將一個16位的半字數據傳送到存儲器中。該半字數據爲源寄存器中的低16位。

指令示例:

STRH R0,[R1] ;將寄存器R0中的半字數據寫入以R1爲地址的存儲器中。

STRH R0,[R1,#8] ;將寄存器R0中的半字數據寫入以R1+8爲地址的存儲器中。

8、STM指令:

S的含義仍然是STORE,與LDM是配對使用的,其指令格式上也相似,即區別於STR,是將堆棧指針寫在左邊,而把寄存器組寫在右邊。

STMFD SP!, {R0}

同樣的,該指令也可理解爲: STMFD [SP]!, {R0}

意思是:把R0保存到堆棧(sp指向的地址)中。


本文來自 BOOK0614 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/u013477200/article/details/50723555?utm_source=copy

**

ARM彙編指令LSL/LSR/ASL/ASR

**
本文摘錄於:http://www.eeworld.com.cn/mcu/2015/0930/article_22693.html
移位
LSL
ASL
LSR
ASR
ROR
RRX
ARM 處理器組建了可以與數據處理指令(ADC、ADD、AND、BIC、CMN、CMP、EOR、MOV、MVN、ORR、RSB、SBC、SUB、TEQ、TST)一起使用的桶式移位器(barrel shifter)。你還可以使用桶式移位器影響在 LDR/STR 操作中的變址值。
譯註:移位操作在 ARM 指令集中不作爲單獨的指令使用,它是指令格式中是一個字段,在彙編語言中表示爲指令中的選項。如果數據處理指令的第二個操作數或者單一數據傳送指令中的變址是寄存器,則可以對它進行各種移位操作。如果數據處理指令的第二個操作數是立即值,在指令中用 8 位立即值和 4 位循環移位來表示它,所以對大於 255 的立即值,彙編器嘗試通過在指令中設置循環移位數量來表示它,如果不能表示則生成一個錯誤。在邏輯類指令中,邏輯運算指令由指令中 S 位的設置或清除來確定是否影響進位標誌,而比較指令的 S 位總是設置的。在單一數據傳送指令中指定移位的數量只能用立即值而不能用寄存器。
下面是給不同的移位類型的六個助記符:
LSL 邏輯左移 ASL 算術左移 LSR 邏輯右移 ASR 算術右移 ROR 循環右移 RRX 帶擴展的循環右移
ASL 和 LSL 是等同的,可以自由互換。
你可以用一個立即值(從 0 到 31)指定移位數量,或用包含在 0 和 31 之間的一個值的寄存器指定移位數量。

邏輯或算術左移
(Logical or Arithmetic Shift Left)
Rx, LSL #n or Rx, ASL #n or Rx, LSL Rn or Rx, ASL Rn
接受 Rx 的內容並按用‘n’或在寄存器 Rn 中指定的數量向高有效位方向移位。最低有效位用零來填充。除了概念上的第 33 位(就是被移出的最小的那位)之外丟棄移出最左端的高位,如果邏輯類指令中 S 位被設置了,則此位將成爲從桶式移位器退出時進位標誌的值。
考慮下列:
MOV R1, #12 MOV R0, R1, LSL#2
在退出時,R0 是 48。 這些指令形成的總和是 R0 = #12, LSL#2 等同於 BASIC 的 R0 = 12 << 2

邏輯右移
(Logical Shift Right)
Rx, LSR #n or Rx, LSR Rn
它在概念上與左移相對。把所有位向更低有效位方向移動。如果邏輯類指令中 S 位被設置了,則把最後被移出最右端的那位放置到進位標誌中。它同於 BASIC 的 register = value >>> shift。

算術右移
(Arithmetic Shift Right)
Rx, ASR #n or Rx, ASR Rn
類似於 LSR,但使用要被移位的寄存器(Rx)的第 31 位的值來填充高位,用來保護補碼錶示中的符號。如果邏輯類指令中 S 位被設置了,則把最後被移出最右端的那位放置到進位標誌中。它同於 BASIC 的 register = value >> shift。

循環右移
(Rotate Right)
Rx, ROR #n or Rx, ROR Rn
循環右移類似於邏輯右移,但是把從右側移出去的位放置到左側,如果邏輯類指令中 S 位被設置了,則同時放置到進位標誌中,這就是位的‘循環’。一個移位量爲 32 的操作將導致輸出與輸入完全一致,因爲所有位都被移位了 32 個位置,又回到了開始時的位置!

帶擴展的循環右移
(Rotate Right with extend)
Rx, RRX
這是一個 ROR#0 操作,它向右移動一個位置 - 不同之處是,它使用處理器的進位標誌來提供一個要被移位的 33 位的數量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章