###### tags: `組合語言` # 組合語言共筆 9 : Load / Store Instructions ## (1) - Load / Store 介紹 Load / Store 是操作 Memory 和 Register,來進行資料的存取與載入 - Load : 從 Memory 載入資料到 Register - Store : 將資料從 Register 儲存到 Memory ![](https://i.imgur.com/KBswtzu.png =400x280) :::info - **指令種類** - **Single Register Load/Store Instruction** : => 單個 Register 的操作,只能操作最多 32 bit 的資料 ( 16, 8 bit ) => 指令 : <font color=blue>LDR / STR</font> - **Multiple Register Load/Store Instruction** : => 使用多個 Register 操作,可以進行一個區塊的操作 => 指令 : <font color=blue>LDMFB / STMFB</font> - **Single Register Swap Instuction** : => 使用一道指令就可將一個 Register 的資料和 Memory 中的"交換" ::: <br> ## (2) - Single Register Load/Store ### - Load/Store 的指令按照以下規律來作設計 :::info `<Opcode>{<cond><size>} Rd, <address>` - <Opcode> : 主指令名稱,代表該指令主要的意義 - <cond> : 此指令加上 Condition ( 前一小節的 Condition Execution ) - <size> : Load / Store 資料的大小,8, 16, 32 bit - Rd : Register - < address > : 記憶體位置(地址) ex : `LDREQB` => `<LDR> <EQ> <B>` ::: ### - 各種 Load/Store 指令 ``` LDR / STR : 對一個 word ( 32 bit ) 作操作 LDRB / STRB : 對一個 Byte ( 8 bit ) 作操作,未達到 32 bit 的 bit 會補 0 LDRH / STRH : 對 half Word ( 16 bit ) 作操作,未達到 32 bit 的 bit 會補 0 LDRSB / LDRSB LDRSH / LDRSH : 主要是加上 S,表示 sign extended to 32 bit, 當[符號位元]=1 補 1,[符號位元]=0 補 0 ( 符號位元為最左邊的數字 ) Ex. 1000 ( 16 bit ) 符號位元 = 1 => 11111000 ( 32 bit ) LDREQB : 加上 Condition <EQ> ``` ### - 用法舉例 :::warning - r1 : 指 R1 暫存器 - [r1] : 指 R1 暫存器存的資料 ``` #### Load 用法 #### ldr r5, [r2] @ 意義是 r2 中存了某個 Memory address(位址) @ 將此 Memory address 中的資料取出 @ 載入存到 r5 中 ldrb r1, [r9, #4] @ 將 r9 中存的 address + 4 @ 並取出 ( r9 + 4 ) 的 Memory 資料 @ ex : 原 address=0x0A00 => 加 4 後 => 0x0A04 @ 載入存到 r1 ldrb r1, [r9, #4]! @ 同理以上 @ 但最後還會將 ( r9 + 4 ) 的新 address 存到 r9 中 @ 覆蓋原 r9 存的 address 資料 ``` ``` #### Store 用法 #### 與 Load 用法類似 str r5, [r2] @ 將暫存在 r5 的資料取出 @ 並將資料存到 r2 中存的 Memory address 指向的 Memory 位置 str r5, [r2, #4] @ 同理以上 @ 只是儲存的 Memory 位置會是原來 r2 中存的 address 加 4 str r5, [r2, #4]! @ 同理以上 @ 並將 ( r2 + 4 ) 的新 address 存入 r2 ``` ::: <br> ## (3) - Load/Store [定址指令]用法整理 這裡是指對使用方式的整理,不會特別寫出 Load/Store 的指令 只列出指令後面的 < address > 的不同操作方式 ### 1. 普通情況 :::info ``` [Rn] // 普通呼叫 Rn == [Rn, #0] [Rn, #<offset_12>] // 呼叫 Rn 並將其儲存的 address 資訊加減 offset [Rn, Rm] // 將 Rm 中存的資訊當作是 offset 與 Rn address 加減 [Rn, Rm, <shift> #<shift_imm>] // 可以對 Rm 存的 offset 做 Scale // - <shift> : 這裡的 shift 可以對 offset 進行 Scale 取代乘法運算,會標示移動方向 // - <shift_imm> : Scale 移動的量 // // ex : LSL#1 // 向左移一位 // 0101 << 1 = 1010 // 向左移一位,數值會從 5 -> 10 // 0100 >> 1 = 0010 // 向右移一位,數值從 4 -> 2 // ``` ::: <br> ### 2. 加入驚嘆號 :::info 加入驚嘆號主要是指會將加上 offset 後的 memory address 存回 Rn 其餘功能則是都相同 ``` [Rn, #<offset_12>]! [Rn, Rm]! [Rn, Rm, <shift> #<shift_imm>]! ``` ::: ### 3. 順序改變 :::info 這邊主要會將操作的順序做一點改變,指令上會是將 offset 獨立出來寫 順序會變成 : 1. 使用原本就存在 Rn 中的 address 做操作(load/store) 2. 之後將 address 加上 offset 儲存到 Rn ``` [Rn], #<offset_12> [Rn], Rm [Rn], Rm, <shift> #<shift_imm> ``` ::: <br> ## (4) - Pointers ### - Pointer 定義 Pointer 的概念類似 C++ 的指標 ( 都稱 pointer ) 可以像是變數的方式來儲存某個記憶體位址,方便取用該位置資料 設定 Pointer 的方式其實就是之前在 [Assembly Syntax 組語句法分類](/0GTXTUZMT-OiYX6YIq4wrg) 中說的 Label ```assembly= /*設定 Pointer [msg] 儲存 "Hello world" 的記憶體位置*/ msg: .asciz "Hello world" ... ``` <br> ### - 使用 Pointer 使用 `=Pointer` 就可以存取到該 pointer 中存的記憶體位置的資料 ```assembly= /*將 Pointer 存放的位址中的資訊 ("Hello world") Load 到 r4 中*/ ldr r4, =msg ``` <br> ## (5) - Loading Constants 常數 ### - 立即值 Immediate Constants 立即值是可以立即取用的 Constant ex : `#4`, 雖然 Register 儲存空間有 32 bit 但立即值的 data 只有 12 bit,其他空間會儲存其他資訊 ( 以後會講 ) <font color=blue>前面說的位址的 offset 就是立即值,所以才會稱 #<offset_12> </font> :::info 12 bit 的空間又存了兩種資訊 - 8 bit : 儲存 constant,如是 unsign 範圍為 [0~255],如是 sign 範圍為 [-127~127] - 4 bit : 剩下 4 bit 儲存了 "旋轉量" 以後還會再提到 ::: <br> ### - MOV 簡介 & Immediate Constants 存取 `mov` 類似 `ldr` 但他只允許在 Register 間做資料的移動,或是讀取 Immediate Constants ```assembly= mov r1, r2 @將 r2 中資料轉移到 r1 mov r0, #0x40 @將立即值 #0x40 存入 r0 ``` <br> ### - Pseudo-Instruction 與 Immediate Constants 存取 可以利用 "**Pseudo-Instruction**" 將 Immediate Constants 存取成類似變數形式 並且會在外生成一個 Constant (literal) pool 來存放 constant :::warning `LDR Rd, =const` ex : ```assembly= MOV r0,=&FF ; MOV r0,#0xFF LDR r0,=&55555555 ; MOV r0,[PC,#Imm10] ``` ::: <br> ## (6) - Multiple Registers Load / Store ### - **介紹語法** Multiple Register 是使用多個 Register 來 Load / Store 資料 其中又分為兩種操作方式 - **Block Copy** : 利用某 Register 存的記憶體位址,來 load/store 連續的記憶體資料 - **Stack Type** : 利用堆疊暫存器 (SP/r13) 來存取當前堆疊頂端位置,並取出堆疊中的資料 :::info **語法** ```assembly= LDM/STM{<variant>} Rd{!}, {Rx-Ry} /*{Rx-Ry}=={Rx,Rx+1...,Ry}*/ ``` ::: :::warning **不同操作方式 Instruction** - **Stack Type** ![](https://i.imgur.com/hc7XUMc.jpg =300x170) - **Block Copy** <font color=blue>**Increment 意義** : 為原來位址再加上 4 byte 也就是移動到下一層 memory ex : 0x0004 => increment => 0x0008 </font> ![](https://i.imgur.com/1yFxAeW.jpg =300x170) ::: <br> ### - **Stack Type** Stack Type 的操作方式會根據 SP 所指向的 Stack Top 位置開始做 Load/Store 並且會更新 SP 的位置 ( Top 位置 ) :::info 這邊範例皆使用 fd (Full Descending) 做舉例 ex : ```assembly= stmfd sp!, {r4,r5,r6} @ 將 r4,r5,r6 中儲存的資訊, @ 存入記憶體中的 Stack, @ 也就是 SP 指向的位置。 */ ldmfb sp!, {r4-r6} @ 從 SP 指向的位置取出資料 @ 並存放在 r4,r5,r6 中。 ``` ::: ### - **Block Copy** Block Copy 是從 <Rd> 指向的記憶體位址,開始取出一連串資料 指令中的差別主要是 Increment、Decrement 的順序 ``` - ia : 在 load/store 完後,再進行 Increment, 意思是,在資料 load/store 完後 <Rd> 會指向最後一個操作資料的位址, ia 會將位址在加上 4 byte (Increment),也就是會指向再下一個記憶體區塊 - ib : 在進行 load/store 之前,就做 Increment, 也就是取出的第一個資料,會是原 <Rd> 指向的下一個位址的資料 - da : 與 ia 的情況類似,但這邊會往下儲存(記憶體 address 減少), 並在 load/store 完資料後再減 4 byte (Decrement) - db : 與 ib 類似,會在 load/store 完資料前先減 4 byte (Decrement) ``` :::info 這邊只用 ia, ib 做舉例 <ia> ex : ```assembly= ldmia r0!, {r1-r3} @ 將 r0 指向的位置連續 load 到 r1,r2,r3 @ 最後進行 Increment ( 0x018 + 4byte = 0x01c ) 存入 r0 ``` ![](https://i.imgur.com/oJ7LTZB.png =400x180) <br> <ib> ex : ```assembly= ldmib r0!, {r1-r3} @ 先進行 Increment 並將位址存入 r0 @ 之後把新的 r0 指向的位置連續 load 到 r1,r2,r3 ``` ![](https://i.imgur.com/e6k5Mkh.png =400x180) ::: <br> ## (7) - Atomic Load/Store (SWP) 這邊簡單介紹一個可以同時做 Load/Store 的指令 Swap (SWP) 顧名思義就是交換,會 Load 資料進來 Rd,並同時將 Rm 的資料存到記憶體 [Rn] ``` SWP{<cond>} Rd, Rm, [Rn] - 將 [Rn] 存的記憶體位置資料 load 到 Rd,並將 Rm 資料存到 Rn 記憶體位置 ex : swpeqb r1, r4, [r3] @ b:byte ``` --- ## Reference - [JoeTheProfessor | 03: ARM Cortex-M Load/Store Instructions](https://www.youtube.com/watch?v=07ATOG5wXPE) - [MEMORY INSTRUCTIONS: LOAD AND STORE (!!推推!!)](https://azeria-labs.com/memory-instructions-load-and-store-part-4/) - [ARM Instruction Set - Multiple Register Load Store Instruction(!!推推!!)](https://www.youtube.com/watch?v=Rpuxgv4coeQ)