ARM體系架構--指令篇
阿新 • • 發佈:2019-01-24
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
===============================================
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
===============================================