數(shù)據(jù)傳送指令之:單寄存器的Load/Store指令
Load/Store內存訪問指令在ARM寄存器和存儲器之間傳送數(shù)據(jù)。ARM指令中有3種基本的數(shù)據(jù)傳送指令。
① 單寄存器Load/Store指令(Single Register)
這些指令在ARM寄存器和存儲器之間提供更靈活的單數(shù)據(jù)項傳送方式。數(shù)據(jù)項可以是字節(jié)、16位半字或32位字。
② 多寄存器Load/Store內存訪問指令
這些指令的靈活性比單寄存器傳送指令差,但可以使大量的數(shù)據(jù)更有效地傳送。它們用于進程的進入和退出、保存和恢復工作寄存器以及拷貝存儲器中的一塊數(shù)據(jù)。
③ 單寄存器交換指令(Single Register Swap)
這些指令允許寄存器和存儲器中的數(shù)值進行交換,在一條指令中有效地完成Load/Store操作。它們在用戶級編程中很少用到。它的主要用途是在多處理器系統(tǒng)中實現(xiàn)信號量(Semaphores)的操作,以保證不會同時訪問公用的數(shù)據(jù)結構。
5.3.1 字數(shù)據(jù)傳送指令這種指令用于把單一的數(shù)據(jù)傳入或者傳出一個寄存器。支持的數(shù)據(jù)類型有字節(jié)(8位)、半字(16位)和字(32位)。
表5.1總結了所有單寄存器的Load/Store指令。
表5.1 單寄存器Load/Store指令
指 令
作 用
操 作
LDR
把一個字裝入一個寄存器
Rd←mem32[address]
STR
將存儲器中的字保存到寄存器
Rd→mem32[address]
LDRB
把一個字節(jié)裝入一個寄存器
Rd←mem8[address]
STRB
將寄存器中的低8位字節(jié)保存到存儲器
Rd→mem8[address]
LDRH
把一個半字裝入一個寄存器
Rd←mem16[address]
STRH
將寄存器中的低16位半字保存到存儲器
Rd→mem16[address]
LDRBT
用戶模式下將一個字節(jié)裝入寄存器
Rd←mem8[address] under user mode
STRBT
用戶模式下將寄存器中的低8位字節(jié)保存到存儲器
Rd→mem8[address] under user mode
LDRT
用戶模式下把一個字裝入一個寄存器
Rd←mem32[address]under user mode
STRT
用戶模式下將存儲器中的字保存到寄存器
Rd→mem32[address] ]under user mode
LDRSB
把一個有符號字節(jié)裝入一個寄存器
Rd←sign{mem8[address]}
LDRSH
把一個有符號半字裝入一個寄存器
Rd←sign{mem16[address]}
1.LDR指令(1)指令編碼格式
LDR指令用于從內存中將一個32位的字讀取到目標寄存器。
指令的編碼格式如圖5.3所示。
圖5.3 LDR指令編碼格式
LDR指令根據(jù)<addr_mode>所確定的地址模式將一個32位字讀取到指令中的目標寄存器<Rd>。如果指令中的尋址方式確定的地址不是字對齊的,則讀出的數(shù)值要進行循環(huán)右移。所移位數(shù)為尋址方式確定的地址bits[1∶0]8的倍,也就是說處理器將取到的數(shù)值作為字的最低位處理。
如果設置了L位,則進行裝載,否則進行存儲。
如果設置了P位,則使用預先變址尋址,否則使用過后變址尋址。
如果設置了U位,則給出的偏移量被加到基址寄存器上,否則從中減去偏移量。
如果設置了B位,傳送內存的一個字節(jié),否則傳送一個字。這在助記符末尾添加后綴“B”,如MOV r7,r5變?yōu)镸OVB r7,r5。
W位的解釋依賴于使用的地址模式。
· 對于預先變址尋址,設置W位強制把它用做地址轉換的最終地址寫回基址寄存器中(例如,傳送的副作用是Rn:= Rn +/-offset。這在匯編器中表示為給指令加上后綴“!”。)。
· 對于過后變址尋址,地址總是寫回,設置 W 位指示在進行傳送之前強制地址轉換。這在匯編器中表示為給指令加上后綴“T”。
當PC作為LDR的目的寄存器<Rd>時,從存儲器取得的數(shù)據(jù)將被當作目標地址值,程序將跳轉到目標地址開始執(zhí)行。
(2)指令的語法格式
LDR{<cond>} <Rd>,<addr_mode>
① <cond>
為指令編碼中的條件域。它指示LDR指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
③ <addr_mode>
它確定了指令編碼中的I、P、U、W、Rn和<addr_mode>位。所有的尋址模式中,都會確定一個基址寄存器Rn。
(3)指令操作的偽代碼
指令操作的偽代碼如下面程序段所示。
If ConditionPassed{cond} then
If address[1:0] == 0b00 then
Value = Memory[address,4]
Else if address[1:0] == 0b01 then
Value = Memory[address,4] Rotate_Right 8
Else if address[1:0] == 0b10 then
Value = Memory[address,4] Rotate_Right 16
Eles /* address[1:0] == 0b11*/
Value = Memory[address,4] Rotate_Right 24
If (Rd is R15) then
If (architecture version 5 or above) then
PC = value AND 0xfffffffe
T Bit = value[0]
Else
PC = value AND 0xfffffffc
Else
Rd = value
(4)指令舉例
LDR r1,[r0,#0x12] ;將r0+12地址處的數(shù)據(jù)讀出,保存到r1中(r0的值不變)
LDR r1,[r0] ;將r0地址處的數(shù)據(jù)讀出,保存到r1中(零偏移)
LDR r1,[r0,r2] ;將r0+r2地址的數(shù)據(jù)讀出,保存到r1中(r0的值不變)
LDR r1,[r0,r2,LSL #2] ;將r0+r2×4地址處的數(shù)據(jù)讀出,保存到r1中(r0,r2的值不變)
LDR Rd,label ;label為程序標號,label必須是當前指令的±4KB范圍內
LDR Rd,[Rn],#0x04 ;Rn的值用作傳輸數(shù)據(jù)的存儲地址。在數(shù)據(jù)傳送后,將偏移量0x04與
Rn相加,結果寫回到Rn中。Rn不允許是r15
注意
地址對齊問題:大多數(shù)情況下,必須保證用于32位傳送的地址是32位對齊的。
2.STR指令(1)指令編碼格式
STR指令用于將一個32位的字數(shù)據(jù)寫入到指令中指定的內存單元。
指令的編碼格式如圖5.4所示。
圖5.4 STR指令編碼格式
(2)指令的語法格式
STR{<cond>} <Rd>,<addr_mode>
① <cond>
為指令編碼中的條件域。它指示STR指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
③ <addr_mode>
它確定了指令編碼中的I、P、U、W、Rn和<addr_mode>位。所有的尋址模式中,都會確定一個基址寄存器Rn。
(3)指令操作的偽代碼
指令操作的偽代碼如下面程序段所示。
If ConditionPassed{cond} then
Memory[address,4]=Rd
(4)指令舉例
LDR/STR指令用于對內存變量的訪問、內存緩沖區(qū)數(shù)據(jù)的訪問、查表、外圍部件的控制操作等等,若使用LDR指令加載數(shù)據(jù)到PC寄存器,則實現(xiàn)程序跳轉功能,這樣也就實現(xiàn)了程序散轉。
① 變量訪問
NumCount EQU 0x40003000 ;定義變量NumCount
LDR R0,=NumCount ;使用LDR偽指令裝載NumCount的地址到R0
LDR R1,[R0] ;取出變量值
ADD R1,R1,#1 ;NumCount=NumCount+1
STR R1,[R0] ;保存變量
② GPIO設置
GPIO—BASE EQU 0xe0028000 ;定義GPIO寄存器的基地址
……
LDR R0,=GPIO—BASE
LDR R1,=0x00ffff00 ;將設置值放入寄存器
STR R1,[R0,#0x0C] ;IODIR=0x00ffff00,IOSET的地址為0xE0028004
③ 程序散轉
…
MOV r2,r2,LSL #2 ;功能號乘以4,以便查表
LDR PC,[PC,r2] ;查表取得對應功能子程序地址,并跳轉
NOP
FUN—TAB DCD FUN—SUB0
DCD FUN—SUB1
DCD FUN—SUB2
…
5.3.2 字節(jié)數(shù)據(jù)傳送指令(LDRB/STRB)1.LDRB指令(1)指令編碼格式
LDRB指令根據(jù)<addr_mode>所確定的地址模式將一個8位字節(jié)讀取到指令中的目標寄存器<Rd>。
指令的編碼格式如圖5.5所示。
圖5.5 LDRB指令編碼格式
注意
LDRB指令加載一個內存地址的8位字節(jié)到一個通用寄存器中。寄存器的高位數(shù)據(jù)補0。
(2)指令的語法格式
LDR{<cond>}B <Rd>,<addr_mode>
① <cond>
為指令編碼中的條件域。它指示LDRB指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
③ <addr_mode>
它確定了指令編碼中的I、P、U、W、Rn和<addr_mode>位。所有的尋址模式中,都會確定一個基址寄存器Rn。
(3)指令操作的偽代碼
if ConditionPassed{cond} then
Rd = Memory[address,1]
注意
當PC作為位基地址出現(xiàn)在指令中時,指令中將會使用PC相關地址,使用這種方法可以編寫自己的位置無關(position-independ)指令。
2.STRB指令(1)指令編碼格式
STRB指令從寄存器中取出指定的8位字節(jié)放入寄存器的低8位,并將寄存器的高位補0。
指令的編碼格式如圖5.6所示。
圖5.6 STRB指令編碼格式
(2)指令的語法格式
STR{<cond>}B <Rd>,<addr_mode>
① <cond>
為指令編碼中的條件域。它指示STRB指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
注意
當PC作為目標寄存器<Rd>出現(xiàn)在指令中時,指令的執(zhí)行結果不可預知。
③ <addr_mode>
它確定了指令編碼中的I、P、U、W、Rn和<addr_mode>位。所有的尋址模式中,都會確定一個基址寄存器Rn。
(3)指令操作的偽代碼
if ConditionPassed{cond} then
Memory[address,1] = Rd[7:0]
5.3.3 半字數(shù)據(jù)傳送指令(LDRH/STRH)1.LDRH指令(1)指令編碼格式
LDRH指令用于從內存中將一個16位的半字讀取到目標寄存器。
如果指令的內存地址不是半字節(jié)對齊的,指令的執(zhí)行結果不可預知。
指令的編碼格式如圖5.7所示。
圖5.7 LDRH指令的編碼格式
(2)指令的語法格式
LDR{<cond>}H <Rd>,<addr_mode>
① <cond>
為指令編碼中的條件域。它指示LDRH指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
注意
如果PC作為目標寄存器,指令的執(zhí)行結果不可預知。
③ <addr_mode>
它確定了指令編碼中的I、P、U、W、Rn和<addr_mode>位。所有的尋址模式中,都會確定一個基址寄存器Rn。
(3)指令操作的偽代碼
if ConditionPassed{cond} then
if address[0]==0
data=Memory[address,2]
else /*address[0]==1*/
data=unpredictable
Rd=data
注意
在包含系統(tǒng)控制協(xié)處理器的芯片應用中,如果定義了地址對齊檢測,當bit[0]!=0時,將發(fā)生地址對齊異常。
2.STRH指令(1)指令編碼格式
STRH指令從寄存器中取出指定的16位半字放入寄存器的低16位,并將寄存器的高位補0。
指令的編碼格式如圖5.8所示。
圖5.8 STRH指令的編碼格式
(2)指令的語法格式
STR{<cond>}H <Rd>,<addr_mode>
① <cond>
指令編碼中的條件域。它指示STRH指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
注意
如果PC作為目標寄存器,指令的執(zhí)行結果不可預知。
③ <addr_mode>
它確定了指令編碼中的I、P、U、W、Rn和<addr_mode>位。所有的尋址模式中,都會確定一個基址寄存器Rn。
(3)指令操作的偽代碼
if ConditionPassed{cond} then
if address[0]==0
data=Rd[15:0]
else /*address[0]==1*/
data=unpredictable
Memory[address,2]=data
5.3.4 用戶模式字數(shù)據(jù)傳送指令(LDRT/STRT)1.LDRT指令(1)指令編碼格式
LDRT指令用于從內存中將一個32位的字讀取到目標寄存器。
指令的編碼格式如圖5.9所示。
LDRT指令根據(jù)<addr_mode>所確定的地址模式將一個32位字讀取到指令中的目標寄存器<Rd>。如果指令中的尋址方式確定的地址不是字對齊的,則讀出的數(shù)值要進行循環(huán)右移。所移位數(shù)為尋址方式確定的地址bits[1∶0]的8倍。也就是說處理器將取到的數(shù)值作為字的最低位處理。
圖5.9 LDRT指令編碼格式
當處理器在特權模式下使用此指令時,內存系統(tǒng)將該操作當作一般用戶模式下得內存訪問指令。
注意
指令的編碼格式中,P位指定位“0”,也就是說LDRT指令的尋址方式為固定尋址方式,即后索引編碼尋址(post_indexed_addressing_mode)。
(2)指令的語法格式
LDR{<cond>}T <Rd>,<post_indexed_addressing_mode>
① <cond>
為指令編碼中的條件域。它指示LDRT指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
③ <post_indexex_address_mode>
使用后索引地址模式尋址。
注意
后索引地址模式中P=0并且W=0(即bit[21]=0、bit[24]=0)。但此指令P=0并且W=1(即bit[21]=1、bit[24]=0)。但實際的尋址操作是一樣的。
(3)指令操作的偽代碼
指令操作的偽代碼如下面程序段所示。
If ConditionPassed{cond} then
If address[1:0]==0b00
Rd=Memory[address,4]
Else if address[1:0]==0b01
Rd=Memory[address,4] Rotate_Right 8
Else if address[1:0]==0b10
Rd=Memory[address,4] Rotate_Right 16
Else address[1:0]==0b11
Rd=Memory[address,4] Rotate_Right 24
2.STRT指令(1)指令編碼格式
STRT指令用于將一個32位的字數(shù)據(jù)寫入到指令中指定的內存單元。
當處理器在特權模式下執(zhí)行此指令時,內存系統(tǒng)將該操作當作一般用戶模式下的內存訪問操作。
指令的編碼格式如圖5.10所示。
圖5.10 STR指令編碼格式
(2)指令的語法格式
STR{<cond>}T <Rd>,<post_indexed_addressing_mode>
① <cond>
為指令編碼中的條件域。它指示STRT指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
③ <post_indexed_address_mode>
使用后索引地址模式尋址,參見LDRT指令。
(3)指令操作的偽代碼
指令操作的偽代碼如下面程序段所示。
If ConditionPassed{cond} then
Memory[address,4]=Rd
5.3.5 用戶模式字節(jié)數(shù)據(jù)傳送指令(LDRBT/STRBT)1.LDRBT指令(1)指令編碼格式
LDRBT指令根據(jù)<post_indexed_addressing_mode>地址模式將一個8位字節(jié)讀取到指令中的目標寄存器<Rd>。
當處理器在特權模式下執(zhí)行此指令時,內存系統(tǒng)將該操作當作一般用戶模式下的內存訪問操作。
指令的編碼格式如圖5.11所示。
圖5.11 LDRBT指令編碼格式
注意
LDRBT指令加載一個內存地址的8位字節(jié)到一個通用寄存器中。寄存器的高位數(shù)據(jù)補0。
(2)指令的語法格式
LDR{<cond>}BT <Rd>,<post_indexed_addressing_mode>
① <cond>
為指令編碼中的條件域。它指示LDRBT指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))
。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
③ <post_indexed_addressing_mode>
使用后索引地址模式尋址,參見LDRT指令。
(3)指令操作的偽代碼
指令操作的偽代碼如下面程序段所示。
If ConditionPassed{cond} then
Rd=Memory[address,1]
2.STRBT指令(1)指令編碼格式
STRBT指令用于將一個8位的字節(jié)數(shù)據(jù)寫入到指令中指定的內存單元。
當處理器在特權模式下執(zhí)行此指令時,內存系統(tǒng)將該操作當作一般用戶模式下的內存訪問操作。
指令的編碼格式如圖5.12所示。
圖5.12 STRBT指令編碼格式
(2)指令的語法格式
STR{<cond>}BT <Rd>,<addr_mode>
① <cond>
為指令編碼中的條件域。它指示LDRBT指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
③ <post_indexed_addressing_mode>
使用后索引地址模式尋址,參見LDRT指令。
(3)指令操作的偽代碼
指令操作的偽代碼如下面程序段所示。
If ConditionPassed{cond} then
Memory[address,1]=Rd[7:0]
5.3.6 有符號的字節(jié)/半字數(shù)據(jù)傳送指令(LDRBT/STRBT)1.LDRSB指令(1)指令編碼格式
LDRSB指令根據(jù)<addr_mode>所確定的地址模式將一個8位字節(jié)讀取到指令中的目標寄存器<Rd>。
注意
LDRSB與LDRB指令的不同之處在于它將寄存器的高24位設置成該字節(jié)數(shù)據(jù)的符號位的值(即將該8位字節(jié)數(shù)據(jù)進行符號位擴展,生成32位字數(shù)據(jù))。
指令的編碼格式如圖5.13所示。
圖5.13 LDRSB指令編碼格式
(2)指令的語法格式
LDR{<cond>}SB <Rd>,<addr_mode>
① <cond>
為指令編碼中的條件域。它指示LDRSB指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
③ <addr_mode>
它確定了指令編碼中的I、P、U、W、Rn和<addr_mode>位。所有的尋址模式中,都會確定一個基址寄存器Rn。
(3)指令操作的偽代碼
If ConditionPassed{cond} then
data=Memory[address,1]
Rd=SignExtend{data}
2.LDRSH指令(1)指令編碼格式
LDRSH指令根據(jù)<addr_mode>所確定的地址模式將一個16位半字讀取到指令中的目標寄存器<Rd>。
注意
LDRSH與LDRH指令的不同之處在于它將寄存器的高16位設置成該字節(jié)數(shù)據(jù)的符號位的值(即將該16位字節(jié)數(shù)據(jù)進行符號位擴展,生成32位字數(shù)據(jù))。
指令的編碼格式如圖5.14所示。
圖5.14 LDRSH指令編碼格式
(2)指令的語法格式
LDR{<cond>}SH <Rd>,<addr_mode>
① <cond>
為指令編碼中的條件域。它指示LDRSH指令在什么條件下執(zhí)行。當<cond>忽略時,指令為無條件執(zhí)行(cond=AL(Alway))。
② <Rd>
確定使用哪個通用寄存器作為目標寄存器。
③ <addr_mode>
它確定了指令編碼中的I、P、U、W、Rn和<addr_mode>位。所有的尋址模式中,都會確定一個基址寄存器Rn。
(3)指令操作的偽代碼
If ConditionPassed{cond} then
if address[0]==0
data=Memory[address,2]
else /*address[0] ==1*/
data=UNPREDICTABLE
Rd=SignExtend{data}