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