1. 程式人生 > >ARM體系架構--指令篇

ARM體系架構--指令篇

add:
add r2, r3, #3  ==> r0=r1+3
add r0, r1, r2  ===> r0=r1+r2
sub:
sub r0, r1, #3  ==> r0=r1-3


rsb:
rsb r0, r1, #3  ==> r0=3-r1
and:
and r0, r1, #0xf  ==> r0=r1 & 0xf  (檢測某位的值)
and r0, r1, #(1<<7)


orr:
orr r0, r1, #0xf   ==> r0=r1 | 0xf
orr r0, r0, #(1<<8)(設定某位的值)


bic:  (清零)
bic r2, r1, #(0x3<<9)(語法,無法清零)
bic r1, r1, #(0x3<<9)  (清零)
eor:
eor r0, r0, #0xf                (翻轉低四位)


修改cpsr
1, 現將cpsr讀取處理
mov r1, r0 (r0代表cpsr)
bic r1, r1, #0x1f
orr r1, r1, #0x13
mov r0, r1

例項用法:
1, mov r0, #0x3  
   mov r0, r1
2, add r0, r1, #0x4
3, sub r0, r1, #0x4
4, mov r3, #0x3
   rsb r2, r3, #0x0
5, 讀取某個值的低四位 
    mov r3, #0x443
    and r1, r3, #0xf  ;==> r1 = r3 & 0xf
6, 設定某個值的[6:4]=0xb
    mov r3, #0x443
    bic r3, r3, #0x70   ; bic r3, r3, #(0x7<<4)  ==> r3 = r3 & ~(0x70) ==> r3 &= ~(0x70)
    orr r3, r3, #0xb0   ; orr r3, r3, #(0xb<<4)  ==> r3 = r3 | 0xb0    ==> r3 |= 0xb0


7,比較指令,一般會去影響到cpsr_f
  cmp實際就是一個減法
  cmp r0, r3
  addeq r3, r1, #0x1
  cmn : 實際是一個加法,負數比較


  tst實際是一個與運算: 測試某些位是否為某個值
           mov r0, r1    (r1代表cpsr)
            tst r0, #0x20 (假如結果為arm態-->測試的結果為0)
         addeq r2, r1, r3  (會執行)
 
  teq實際是一個異或運算: 測試某些位是否為某個值
          mov r0, r1    (r1代表cpsr)
  teq r0, #0x13  (假如結果為svc模式)
  addeq r2, r1, r3  (會執行)


條件碼:
eq : equal
ne : not equal

有符號:
GE : great and equal 大於等於
GT : greater than  小於
LT : less than  小於

大於 小於:
無符號:
CS  : carry set  大於等於
CC  : carry clear 小於

=========================================================
移位操作:
add r0, r2, r2, LSL #2
r0 = r2 + r2<<2
   = 5 * r2

立即數:
在機器碼中對立即數進行了一個編碼方式:
低12位 =   4bit移位數 +8bit常量


32bit的立即數在機器碼如何表示:  
常量 << 4bit移位數 * 2


立即數的使用是有限制: 合法和不合法的立即數
   1, 在立即數中找到一個8bit的常量(找第一個1和最後一個1)
   2, 立即數能夠通過這個常量移動偶數位得到
編譯器自動會判斷是否合法


如果不合法: ldr r0, =0x12345678
===============================================================
單暫存器資料傳送: (記憶體和暫存器之間的資料互動)
load/store 

ldr/str:
從0x20000000記憶體中載入一個數據:
mov r0, #0x20000000
ldr r1, [r0]


儲存一個數據
mov r0, #0x20000000
mov r1, #0x56
str r1, [r0]


載入偏移某個基準地址上的值:
mov r0, #0x20000000
前索引
ldr r1, [r0, #0x40]  ; 先計算地址,然後運算, r0這個值不會發生變化
==> r1 = [0x20000040]
==> r0 =  0x20000000
後索引
ldr r1, [r0], #0x40  ; 先做運算,然後基地址會發生變化, r0這個值會發生變化
==> r1 = [0x20000000]
==> r0 =  0x20000040


ldr的總結:
1, 給暫存器賦值任何立即數
ldr r0, =0x12345678
2, 間接取記憶體資料
ldr r0, =0x20000000
ldr r1, [r0]
3, 根據基地址進行間接定址:
ldr r1, [r0, #0x40]
ldr r1, [r0], #0x40


4, 直接獲取標籤的地址:
ldr r0, =dataAddress
ldr r1, [r0], #0x4


5, 直接取標籤中的值
ldr r0, dataAddress
ldr r1, r0
mydata
dcd  0x2

================================================================
多暫存器操作:
記憶體地址升降
I: increase, 
D : decrease 
記憶體地址增加增加/降低的時候
A: after
B: before


ldr r10, =0x30000000
ldmxx r10, {r0,r1,r4}
// r10 一定是記憶體地址
//方向, 從記憶體中將資料載入到暫存器中


ldr r10, =0x30000000
stmxx r10, {r0,r1,r4}
// r10 一定是記憶體地址
//方向, 從暫存器中將資料儲存到記憶體中


注意的規則:
1,暫存器列表中: 連續暫存器: r4-r7
不連續暫存器:  r2, r4-r7
2, 高記憶體地址對應大暫存器
3,如果記憶體基地址帶了一個!, 那麼隨著操作記憶體的基地址會更新 
stmxx r10!, {r0,r1,r4} 

==============================================
棧操作:
壓棧
stmfd sp!, {r0-r12, lr}
出棧:
ldmfd sp!, {r0-r12, lr}
如果有個^
ldmfd sp!, {r0-r12, lr}^, 意味著在模式切換的時候,會自動將spsr_<mode> --> cpsr


=======================================================
軟中斷指令:
swi num  
1,num是自定義, 軟中斷會分成很多種
2, 一旦執行swi, cpu就會產生軟中斷異常



========================================================
對cpsr和spsr進行讀寫操作指令:
mrs : 讀操作
mrs r0, cpsr

msr : 寫操作
msr cpsr, r0


模式切換: 切換到system模式, 將IRQ禁止掉
mrs r0, cpsr
bic r0, r0, #0x9f
orr r0, r0, #0x9f
msr cpsr, r0

====================================
協處理器指令:
mrc : 讀取協處理器中的暫存器值
   mrc p15, 0, r9, c0, c1,0 
mcr : 修改協處理器中的暫存器值
   mcr  p15, 0, r9, c0, c1,0 
======================================
thumb態
ldr r0, =toThumb+1  ; 由於thumb中地址是以位元組為對其的,
   bx r0  ; 忽略第0位,但是該為會作為標誌 
code16
toThumb
mov r5, #0x0
ldr r0, =toArm ;[0]=0作為標誌
bx  r0
toArm
add r2, r1, r0


===============================================