ARM Cortex-M3 學(xué)習(xí)筆記(4-2)
第四章 指令系統(tǒng)
數(shù)據(jù)傳送類指令
寄存器到寄存器傳送:MOV 指令、MVN指令
MOV R8, R3; R8 = R3
MVN R8, R3; R8 = -R3
學(xué)過微機(jī)原理的都應(yīng)記得,x86中一條MOV 指令存儲(chǔ)器和寄存器間的任意傳送。ARM 中是不行的,這也是CISC和RISC 內(nèi)核的一個(gè)比較明顯的區(qū)別。
存儲(chǔ)器到寄存器傳送:LDRx 指令、LDMxy指令
寄存器到存儲(chǔ)器:STRx 指令、STMxy指令
LDRx 指令的x可以是B(byte)、H(half word)、D(Double word)或者省略(word),具體的用法如下:
本文引用地址:http://m.butianyuan.cn/article/201611/318847.htm示例 | 功能描述 |
LDRB Rd, [Rn, #offset] | 從地址Rn+offset處讀取一個(gè)字節(jié)送到Rd |
LDRH Rd, [Rn, #offset] | 從地址Rn+offset處讀取一個(gè)半字送到Rd |
LDR Rd, [Rn, #offset] | 從地址Rn+offset處讀取一個(gè)字送到Rd |
LDRD Rd1, Rd2, [Rn, #offset] | 從地址Rn+offset處讀取一個(gè)雙字(64位整數(shù))送到Rd1(低32位)和Rd2(高32位)中。 |
STRx 指令的x同樣可以是B(byte)、H(half word)、D(Double word)或者省略(word),具體的用法如下:
示例 | 功能描述 |
STRB Rd, [Rn, #offset] | 把Rd中的低字節(jié)存儲(chǔ)到地址Rn+offset處 |
STRH Rd, [Rn, #offset] | 把Rd中的低半字存儲(chǔ)到地址Rn+offset處 |
STR Rd, [Rn, #offset] | 把Rd中的低字存儲(chǔ)到地址Rn+offset處 |
STRD Rd1, Rd2, [Rn, #offset] | 把Rd1(低32位)和Rd2(高32位)表達(dá)的雙字存儲(chǔ)到地址Rn+offset處 |
LDRx和STRx指令還有一種帶預(yù)索引的格式,下面舉個(gè)例子(注意語句中的“!”):
LDR.W R0,[R1, #20]! ;預(yù)索引
上面語句的意思是先把地址R1+offset處的值加載到R0,然后,R1 ßR1+ 20
還有一種后索引形式,注意與上面的預(yù)索引的區(qū)別(還要注意語句中沒有“!”):
STR.W R0, [R1], #-12 ;把R0的值存儲(chǔ)到地址R1處。完畢后, R1ßR1+(-12)
LDMxy指令和STMxy指令可以一次傳送更多的數(shù)據(jù)。
X可以為要I或D,I表示自增(Increment),D表示自減(Decrement)。
Y可以為A或B,表示自增或自減的時(shí)機(jī)是在每次訪問前(Before)還是訪問后(After)。
另外,指令帶有“.W”后綴表示這條指令是32位的Thumb-2指令,否則是16位的指令。
示例 | 功能描述 |
LDMIA Rd!, {寄存器列表} | 從Rd處讀取多個(gè)字,并依次送到寄存器列表中的寄存器。每讀一個(gè)字后Rd自增一次,16位指令 |
LDMIA.W Rd!, {寄存器列表} | 從Rd處讀取多個(gè)字,并依次送到寄存器列表中的寄存器。每讀一個(gè)字后Rd自增一次 |
STMIA Rd!, {寄存器列表} | 依次存儲(chǔ)寄存器列表中各寄存器的值到Rd給出的地址。每存一個(gè)字后Rd自增一次,16位指令 |
STMIA.W Rd!, {寄存器列表} | 依次存儲(chǔ)寄存器列表中各寄存器的值到Rd給出的地址。每存一個(gè)字后Rd自增一次 |
LDMDB.W Rd!, {寄存器列表} | 從Rd處讀取多個(gè)字,并依次送到寄存器列表中的寄存器。每讀一個(gè)字前Rd自減一次 |
STMDB.W Rd!, {寄存器列表} | 存儲(chǔ)多個(gè)字到Rd處。每存一個(gè)字前Rd自減一次 |
這里需要特別注意!的含義,它表示要自增(Increment)或自減(Decrement)基址寄存器Rd的值,時(shí)機(jī)是在每次訪問前(Before)或訪問后(After)。比如:
假設(shè) R8=0x8000,則
STMIA.W R8!, {R0-R3} ; R8值變?yōu)?x8010
STMIA.W R8, {R0-R3} ; R8值不變
上面兩行代碼都是將R0-R3共16個(gè)字節(jié)的數(shù)據(jù)存儲(chǔ)到從0x8000開始的16個(gè)字節(jié)空間中,唯一的區(qū)別是第一條指令執(zhí)行完后R8被更新為0x8010,而第二條指令不更新R8。
立即數(shù)的加載
MOV支持8位立即數(shù)加載,比如:
MOV R0, #0x12
32位指令MOVW(加載到寄存器的低16位)和MOVT(加載到寄存器的高16位)可以支持16位立即數(shù)加載。如果要加載32位的立即數(shù),必須先使用MOVW,再使用MOVT,因?yàn)镸OVW會(huì)清零高16位。
LDR 和ADR的區(qū)別
LDR和ADR都是偽指令,都可以用來加載一個(gè)立即數(shù)(也可以是一個(gè)地址),如果加載的是程序地址,LDR會(huì)自動(dòng)地把LSB置位,ADR則不會(huì):
LDR R0, =address1 ; R0= 0x4000 | 1
ADR R1, address1 ; R1= 0x4000。注意:沒有“=”號(hào)
…
address1
0x4000: MOV R0, R1
特殊功能寄存器只能用MSR/MRS指令訪問:
MRS
MSR
下面是兩個(gè)例子:
MRS R0, PRIMASK ; 讀取PRIMASK到R0中
MSR BASEPRI, R0 ;寫入R0到BASEPRI中
但是需要注意大多數(shù)的特殊功能寄存器都只能在特權(quán)級(jí)下訪問,非特權(quán)級(jí)下只能訪問APSR
評(píng)論