訪存指令
訪存指令用于數(shù)據(jù)在存儲器和處理器寄存器之間傳遞裙盾。有三種訪存指令:單寄存器傳輸指令、多寄存器傳輸指令,交換指令噪珊。
1. 單寄存器傳輸指令
- 概念:這些指令用于將單數(shù)據(jù)移入和移出寄存器谤职。數(shù)據(jù)類型支持有符號和無符號字長(32-bits)饰豺,半字長(16-bits)和字節(jié)。
-
常用的單寄存器傳輸指令 及其 語法
其中:
addressing1(數(shù)據(jù)類型是word, unsigned byte)可用桶形移位器-比例因子是2的倍數(shù)允蜈;
addressing2(數(shù)據(jù)類型是半字冤吨,有符號半字蒿柳,有符號字節(jié),以及雙字)。
- LDR,STR 指令
LDR只在存儲器加載32-bit字長地址漩蟆,4字節(jié)的倍數(shù)-0垒探,4,8...怠李。
示例1.1
以下示例為從寄存器r1中包含的內(nèi)存地址進行加載圾叼,然后將存儲返回到存儲器中的相同地址。
寄存器r1:
第一條指令:加載寄存器r1指向的內(nèi)存地址的內(nèi)容到寄存器r0捺癞。
目標寄存器r0:
第二條指令:存儲寄存器r0的內(nèi)容到寄存器r1指向的內(nèi)存地址。
r1 的偏移為0惕鼓,寄存器r1為基地址寄存器唐础。
單寄存器尋址模式
ARM指令集提供了不同的尋址模式箱歧。這些模式結合了索引方法:帶寫回的預索引,預索引和后索引彻犁。
索引方法如下表所示:
示例1.2:
-
帶寫回的預索引
通過基寄存器地址加上地址偏移的計算汞幢,然后更新基寄存器地址為新地址驼鹅。該模式用于遍歷數(shù)組。
解析:
基寄存器r1:
r1地址和偏移量相加森篷,新地址為:mem32[0x00009000+0x00000004] -- mem32[0x00009004],基寄存器r1地址更新為這個新地址:即 r1 = 0x00009004仲智;
目標寄存器r0:
加載更新后的寄存器r1指向的內(nèi)存地址的內(nèi)容到r1。
mem32[0x00009004] = 0x02020202, r1現(xiàn)在地址存儲的內(nèi)容是 0x02020202剪验,即r0 = 0x02020202
-
預索引
與上面相反前联,索引偏移和帶寫回的預索引一樣但是不更新基寄存器地址。該模式用于在訪問數(shù)據(jù)結構中的元素時間啸臀。
解析:
基寄存器r1:
r1地址和偏移量相加烁落,新地址為:mem32[0x00009000+0x00000004] -- mem32[0x00009004]豌注,基寄存器r1地址地址不更新灯萍,不變,即 r1 = 0x00009000目標寄存器r0:
r1的地址不變属桦,但是由于偏移后的地址為0x00009004他爸,mem32[0x00009004] = 0x02020202, 即r0 = 0x02020202
-
后索引
當?shù)刂繁挥昧艘院笾皇歉禄拇嫫鞯刂贰T撃J接糜诒闅v數(shù)組系谐。
解析:
基寄存器r1:
r1地址和偏移量相加讨跟,新地址為:mem32[0x00009000+0x00000004] -- mem32[0x00009004]纪他,因為地址被用了,所以只更新基寄存器r1地址更新為這個新地址:即 r1 = 0x00009004晾匠;目標寄存器r0:
在這個模式下,目標寄存器加載源地址指向的內(nèi)容薪寓。mem32[0x00009000] = 0x01010101, 即 r0 = 0x01010101澜共。
小結:
示例1.2 使用了preindex方法,展現(xiàn)了每一個索引方法是如何影響 寄存器 r1 地址的母谎,以及加載到 寄存器 r0 中的數(shù)據(jù)內(nèi)容京革。每一個指令展現(xiàn)了在同一個先決條件的索引方法結果。-
總結1:
下表為LDR 指令的不同變化:
總結2:
下表為使用16-bits半字長或有符號字節(jié)數(shù)據(jù)訪存時可用的尋址方式:
2. 多寄存器傳輸指令
- 概念:多寄存器傳輸指令在一個指令下,可以在內(nèi)存和寄存器中傳遞多個寄存器来惧。傳輸從指向存儲器的基地址寄存器Rn開始供搀;多寄存器傳輸指令可提高效率,例如:數(shù)據(jù)塊的操作葛虐,上下文切換屿脐,堆棧操作;
多寄存器傳輸指令會增加中斷延時(不會打斷正在執(zhí)行的指令)的诵。ARM不支持經(jīng)常中斷當執(zhí)行的時候。
編譯器比如armcc提供了switch指令可以控制一條load-store指令最大寄存器數(shù)目烦粒,限制了最大中斷延遲代赁。 - 常用的多寄存器傳輸指令 及其 語法
下表為多寄存器傳輸指令的不同尋址模式芭碍,N 為寄存器個數(shù)。
基地址寄存器Rn決定了多寄存器傳輸指令的源地址和目標地址忧勿。通過下面的轉換艇拍,寄存器可以自動更新。
IA 執(zhí)行后增加
IB 執(zhí)行前增加
DA 執(zhí)行后減少
DB 執(zhí)行前減少
更新基地址的load-store指令對层释,用于類似成對的push pop操作快集,
STMIA - LDMDB
STMIB - LDMDA
STMDA - LDMIB
STMDB - LDMIALDMIA 指令示例:
下例中,寄存器r0是基寄存器Rn階乘乖寒,表示指令執(zhí)行后更新寄存器院溺。可以注意到逐虚,在多寄存器傳輸指令中寄存器沒有單獨列出,而是用符號 " - " 代表一段寄存器范圍撮躁。在這個例子中买雾,寄存器范圍是從寄存器r1 到 r3。
每一個寄存器可以列出嗤军,用圓括號 { 和 } 來分開每一個寄存器晃危。
在先決條件下山害,基址寄存器r0指向的內(nèi)存地址為 0x80010 ,內(nèi)存地址0x80010冤荆,0x80014和0x80018上相應存儲的值是0x01,0x02 和 0x03.
下圖為圖形表示:
多寄存器傳輸指令LDMIA執(zhí)行后权纤,寄存器r1, r2 和 r3 包含的值如下圖所示:
基寄存器r0 在上個字長加載以后,現(xiàn)在指向內(nèi)存地址 0x8001c外邓。
- LDMIB指令示例
使用和上面相同的LDMIA 指令 中的Per-condition损话,寄存器r0指向的第一個字長忽略槽唾,寄存器r1從下一個內(nèi)存地址加載,如下圖所示:
多寄存器傳輸LDMIB指令執(zhí)行后,寄存器r0 現(xiàn)在指向最后一次被加載后的內(nèi)存地址 0x8001c拧烦,和LDMIA指向下一個內(nèi)存地址相反
LDMDA和LDMDB 指令從起始地址減少并存儲到上升的內(nèi)存地址钝计。
使用增加和減少的多寄存器傳輸指令齐佳,可以前向和后向訪問數(shù)組重虑,允許堆棧的push和pull操作秦士。
堆棧操作
ARM結構用多存儲器傳輸指令執(zhí)行堆棧操作永高。
pop : 從堆棧中移除數(shù)據(jù)
push: 數(shù)據(jù)放入堆棧
在使用堆棧時要決定是 ascending(A)還是 descending(D): 升序是堆棧朝著高地址增長,降序是朝著低地址增長曹傀。
堆棧3個屬性饲宛,堆棧基址幕庐、堆棧指針(sp)家淤、堆棧限制;
當使用full stack(F)絮重,sp指向最后一個地址或滿地址青伤;
當使用empty stack(E),sp指向第一個或空的地址狠角。
ARM-Thumb過程調(diào)用標準(ATPCS)定義了例程如何被調(diào)用和寄存器如何分配丰歌;
ATPCS定義堆棧為遞減式滿堆棧(Descending-Full stack);
堆棧檢查enable時,ATPCS定義r10為堆棧限制或sl(stack limit)动遭; 備注:push堆棧溢出錯誤厘惦,pop堆棧下溢(stack underflow)錯誤哩簿。
下表為支持堆棧操作的可用尋址方式:
3. 交換指令
- 概念:交換指令是一個特殊的訪存指令酝静。它交換內(nèi)存?zhèn)€寄存器的內(nèi)容。是原子操作宗苍,會占據(jù)總線薄榛,直至交換完成。
-
常用的交換指令 及其 語法:
交換不能被其他指令或總線訪問中斷丽啡,這是系統(tǒng)占用總線直到完成硬猫。
-
示例:Swap指令從內(nèi)存加載一個字長到寄存器r0啸蜜,然后用寄存器r1覆寫內(nèi)存。
這個指令在一個操作系統(tǒng)中當生成信號量semaphore和互斥時特別有用霞丧。