ARM彙編指令的一些總結[轉]

ARM彙編指令的一些總結ARM彙編指令很多,但是真正常用的不是很多,而且需要認真琢磨的又更少了。
         比較有用的是MOV B BL LDR STR
         @ disable watch dog timer
         mov r1, #0x53000000 //立即數尋址方式

   mov r2, #0x0
str r2, [r1]
MOV沒有什麼好說的,只要掌握幾個尋址方式就可以了,而且ARM的尋址方式比386的簡單很多。立即數尋址方式,立即數要求以“#”作前綴,對於十六進制的數,還要求在#後面加上0x或者&。0x大家很好理解。有一次我碰到了&ff這個數,現在才明白跟0xff是一樣的。
STR是比較重要的指令了,跟它對應的是LDR。ARM指令集是加載/存儲型的,也就是說它只處理在寄存器中的數據。那麼對於系統存儲器的訪問就經常用到STR和LDR了。STR是把寄存器上的數據傳輸到指定地址的存儲器上。它的格式我個人認爲很特殊:
STR(條件) 源寄存器,<存儲器地址>
比如 STR R0, [R1] ,意思是R0-> [R1],它把源寄存器寫在前面,跟MOV、LDR都相反。
LDR應該是非常常見了。LDR就是把數據從存儲器傳輸到寄存器上。而且有個僞指令也是LDR,因此我有個百思不得其解的問題。看這段代碼:
mov r1, #GPIO_CTL_BASE
add r1, r1, #oGPIO_F
ldr r2,=0x55aa // 0x55aa是個立即數啊,前面加個=幹什麼?
str r2, [r1, #oGPIO_CON]
mov r2, #0xff
str r2, [r1, #oGPIO_UP]
mov r2, #0x00
str r2, [r1, #oGPIO_DAT]
對於當中的ldr 那句,我就不明白了,如果你把=去掉,是不能通過編譯的。我查了一些資料,個人感覺知道了原因:這個=應該表示LDR不是ARM指令,而是僞指令。作爲僞指令的時候,LDR的格式如下:
LDR 寄存器, =數字常量/Label
它的作用是把一個32位的地址或者常量調入寄存器。嗬嗬,那大家可能會問,
“MOV r2,#0x55aa”也可以啊。應該是這樣的。不過,LDR是僞指令啊,也就是說編譯時編譯器會處理它的。怎麼處理的呢?——規則如下:如果該數字常量在MOV指令範圍內,彙編器會把這個指令作爲MOV。如果不在MOV範圍中,彙編器把該常量放在程序後面,用LDR來讀取,PC和該常量的偏移量不能超過4KB。
這麼一說,雖然似懂非懂,但是能夠解釋這個語句了。
僞指令LDR{cond} register, ={expr|label-expr}
expr爲32位常量。編譯器根據expr的取值情況來處理這條僞指令:
1、當expr表示的地址沒有超過mov或mvn指令中地址的取值範圍時,編譯器用合適的mov指令或mvn指令代替該LDR僞指令。
2、當expr表示的地址超過了mov或mvn指令中地址的取值範圍時,編譯器將該常數放在緩衝區中,同時用一條基於PC的LDR指令讀取該常數。
...............................
通過上面兩種可以得出僞指令LDR和ARM指令LDR的區別,具體使用時,可以不用考慮二者的區別,由編譯器決定的,看源碼時,你只要搞清楚它的功能就行。
然後說一下跳轉指令。ARM有兩種跳轉方式。
(1) mov pc <跳轉地址〉
這種向程序計數器PC直接寫跳轉地址,能在4GB連續空間內任意跳轉。
(2)通過 B BL BLX BX 可以完成在當前指令向前或者向後32MB的地址空間的跳轉(爲什麼是32MB呢?寄存器是32位的,此時的值是24位有符號數,所以32MB)。
B是最簡單的跳轉指令。要注意的是,跳轉指令的實際值不是絕對地址,而是相對地址——是相對當前PC值的一個偏移量,它的值由彙編器計算得出。
BL非常常用。它在跳轉之前會在寄存器LR(R14)中保存PC的當前內容。BL的經典用法如下:
bl NEXT ; 跳轉到NEXT
……
NEXT
……
mov pc, lr ; 從子程序返回。
最後提一下Thumb指令。ARM體系結構還支持16位的Thumb指令集。Thumb指令集是ARM指令集的子集,它保留了32位代碼優勢的同時還大大節省了存儲空間。由於Thumb指令集的長度只有16位,所以它的指令比較多。它和ARM各有自己的應用場合。對於系統性能有較高要求,應使用32位存儲系統和ARM指令集;對於系統成本和功耗有較高要求,應使用16位存儲系統和ARM指令集。


###################################################################################################

###################################################################################################

LDR STR——用於字和無符號字
指令格式
LDR/STR{cond}{T} Rd<地址>
LDR/STR{cond}B{T} Rd<地址>

LDR{cond}{T} Rd<地址>   加載指定地址的字數據到Rd中;
STR{cond}{T}  Rd<地址>    存儲Rd中的字數據到指定的地址單元中;
LDR{cond}B{T} Rd<地址>    指令加載指定地址的字節數據到Rd的的最低字節中(Rd的高24位清零);
STR{cond}B{T} Rd<地址>   指令存儲Rd中的最低字節數據到指定的地址單元中。
     T爲可選後綴,若有T,那麼即使處理器是在特權模式下,存儲系統也將訪問看成處理器是在用戶模式下,T 在用戶模式下無效,不能與前索引偏移一起使用T
 
地址部分可用的形式有4種:
  • 零偏移(zero offset) [Rn] Rn的值作爲傳送數據的地址。如
    LDR R0,[R1]
  • 前索引偏移(pre-indexed offset) [RnFlexoffset]{!} 在數據傳送之前,將偏移量Flexoffset加到Rn 中。其結果作爲傳送數據的存儲器地址。若使用後綴“!”,則結果寫回到Rn 中,且Rn 不允許是R15,如:
    LDRB R0,[R1,#8]
    LDR R0,[R1,#8]!
  • 程序相對偏移(program relative) label(label 必須是在當前指令的土4KB 範圍內) 。
    程序相對偏移是前索引形式的另一種版本。從PC 計算偏移量,並將PC 作爲Rn 生成前索引指令,不能使用後綴“!”,如:
    LDR R0,place ;
    place地址裝入R0
  •  後索引偏移(post-indexed offset) [Rn],Flexoffset。在數據傳送後,將偏移量Flexoffset 加到Rn 中,結果寫回到Rn,Rn 不允許是R15,如:
    LDR R0,[R1],R2,LSL#2 ;
    將存儲器地址爲R1 的字數據讀入寄存器R0,並將新地址R1+R2×4寫入R1。
    偏移量Flexoffset可以是下兩種形式之:
    1) 取值範圍是-4095 到+4095 的整數的表達式,經常是數字常量,如:
    STR R5,[R7],#--8
    2) 一個寄存器再加上移位(移位由立即數指定),如:
    {-}Rm{,shift}
    其中:
    - :可選負號。若帶符號“一”,則從Rn 中減去偏移量。否則,將偏移量加到Rn 中。
    Rm :內含偏移量的寄存器。Rm 不允許是R15
    Shift:Rm 的可選移位方法。可以是下列形式的任何一種:
    ASR n :算術右移n 位(1<=n<=32)
    LSL n :邏輯左移n 位(1<=n<=31)
    LSR n :邏輯右移n 位(1<=n<=32)
    ROR n :循環右移n 位(1<=n<=31)
    RRX :循環右移1 位,帶擴展。
AND―――――邏輯"與"操作指令
指令格式:
AND{cond}{S} Rd,Rn,operand2
AND指令將操作數operand2 與Rn 的值按位邏輯"與",結果存放到目的寄存器Rd 中。若設置S,則根據運算結果影響N、Z位,在計算第二操作數時,更新C位,不影響V位(指令ORR、EOR、BIC 對標誌位的影響同AND 指令)。
指令示例:
ANDS R1,R1,R2  ;R1=R1&R2,並根據運算的結果更新標誌位
AND R0,R0,#0x0F ;R0=R0&0x0F,取出R0最低4位數據。

ORR―――――邏輯"或"操作指令
指令格式:ORR{cond}{S} Rd,Rn,operand2 ORR指令將操作數operand2 與Rn 的值按位邏輯"或",結果存放到目的寄存器Rd 中。指令示例:
ORRS R1,R1,R2 ;R1=R1|R2,並根據運算的結果更新標誌位
ORR R0,R0,#0x0F ;R0=R0|0x0F,將R0最低4位置1,其餘位不變。
 
BIC―――――位清除指
指令格式
BIC{cond}{S} Rd,Rn,operand2
BIC指令將Rn 的值與操作數operand2 的反碼按位邏輯"與",結果存放到目的寄存器Rd 中。指令示例:BIC R0,R0,#0x0F ;將R0最低4位清零,其餘位不變。
 
CMP―――――比較指令
指令格式:
CMP{cond} Rn,operand2
CMP指令用Rn的值減去操作數operand2 ,並將結果的狀態(Rn 與operand2比較是大、小、相等)反映在CPSR中,以便後面的指令根據條件標誌決定程序的走向。CMP指令與SUBS指令完成的操作一樣,只是CMP指令只減,不存結果。
指令示例:
cmp R0,R1 ;比較R0,R1
beq stop ;R0=R1跳到stop
blt less ;R0<R1跳到Less

.
.
.

Less:
.
.
.
Stop:
.
.
.
SUB―――――減法運算指令
指令格式:
SUB{cond}{S} Rd,Rn,operand2 SUB指令用Rn 的值減去操作數operand2 ,並將結果存放到目的寄存器Rd 中。 指令示例:
SUBS R1,R1,R2 R1=R1-R2,並並根據運算的結果更新標誌位
SUBGT R3,3,#1 ;大於則 R3=R3-
SUB R0,R2,R3,LSL#2; R0=R2-(R3<<2)
 
ARM分支指令

助記符

說明

操作

B{cond} lable

分支指令

PC← lable

BL{cond} lable

帶鏈接的分支指令

LRPC-4 ,PC←lable

BX{cond} Rm

帶狀態切換的分支指令

PC← Rm,切換處理器狀態

 
 指令的條件碼
 條件碼  助記符後綴  標誌  含義
 0000  EQ  Z置位(Z=1) 相等 
 0001  NE  Z清零(Z=0) 不相等 
 0010  CS  C置位  無符號數大於等於
 0011  CC  C清零  無符號數小於
 0100  MI  N置位 負數 
 0101  PL  N清零 整數或0 
 0110  VS  V置位  溢出
 0111  VC  V清零  未溢出
 1000  HI  C置位且Z清零  無符號數大於
 1001  LS  Z置位且C清零  無符號數小於等於
 1010  GE  N等於V(N=V=1或N=V=0)  帶符號數大於或等於
 1011  LT  N不等於V  帶符號數小於
 1100  GT  Z清零且N等於V  帶符號數大於
 1101  LE  Z置位或N不等於V  帶符號數小於或等於
 1110  AL  忽略 無條件執行 


;GPIO寄存器宏定義
GPFCON EQU 0x56000050
GPFDAT EQU 0x56000054
GPFUP EQU 0x56000058    

EXPORT LEDTEST
AREA LEDTESTASM,CODE,READONLY ;該僞指令定義了一個代碼段,段名爲LEDTESTASM,屬性只讀

LEDTEST
;設置GPF4-GPF7爲output
ldr r0,=GPFCON
ldr r1,[r0]
bic r1,r1,#0xff00
orr r1,r1,#0x5500
str r1,[r0]

;禁止GPF4-GPF7端口的上拉電阻
ldr r0,=GPFUP
ldr r1,[r0]
orr r1,r1,#0xf0
str r1,[r0]

looptest
;將數據端口F的數據寄存器的地址附給寄存器r2
ldr r2,=GPFDAT

ldr r3,[r2]
bic r3,r3,#0xf0
orr r3,r3,#0xb0
str r3,[r2] ;GPF6 output 0
ldr r0,=0x2fffff
bl delay ;調用延遲子程序

ldr r3,[r2]
bic r3,r3,#0xf0
orr r3,r3,#0x70
str r3,[r2] ;GPF7 output 0
ldr r0,=0x2fffff         ;初始計數值
bl delay ;調用延遲子程序

ldr r3,[r2]
bic r3,r3,#0xf0
orr r3,r3,#0xd0
str r3,[r2] ;GPF5 output 0
ldr r0,=0x2fffff
bl delay ;調用延遲子程序

ldr r3,[r2]
bic r3,r3,#0xf0
orr r3,r3,#0xe0
str r3,[r2] ;GPF4 output 0
ldr r0,=0x2fffff
bl delay      ;調用延遲子程序

b looptest
delay
sub r0,r0,#1 ;r0=r0-1
cmp r0,#0x0 ;將r0的值與0相比較
bne delay ;比較的結果不爲0(r0不爲0),繼續調用delay,否則執行下一條語句
mov pc,lr ;返回

END ;程序結束符

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