# 組合語言 ## CH1 An Overview of Computing Systems 計算系統概述 ### 問題 #### What is an assembler? 把彙編語言書寫的程式翻譯成與之等價的機器語言程式的翻譯程式。 彙編程式輸入的是用彙編語言書寫的源程式,輸出的是用機器語言表示的目標程式。 #### What hardware and software are needed? Editor, Assembler, Linker, Debugger(編譯器、彙編程式、連結器、偵錯工具) #### What does assembly language related to machine language? 組合語言程式指令與機器語言指令呈一對一的關係;但組合語言所寫的程式,機器無法接受,因此必須透過系統所提供的組合程式加以組譯,才能為機器所接受並加以執行。 #### Is assembly language portable(移植)? 組合語言對應著不同的機器語言指令集。 一種組合語言專用於某種電腦系統結構 #### Why learn assembly language? * Write ==embedded system programs(嵌入式系統程式)== * To be ==highly optimized(高度最佳化)== for both space and run time speed * Overall understanding of interaction between the computer hardware, ==operating system(作業系統)==, and application programs * Break through the ==limitations(限制)== of high level languages in certain types of operations * Create ==device drivers(設備驅動程式)== for the equipment ### 語言易讀性 ![image](https://hackmd.io/_uploads/SJ1oS_qQa.png) 由高到低:高階語言、組合語言、作業系統、指令集架構、微架構、數位邏輯 ex: English:   Display the sum of A times B plus C. C++:    cout<<(A * B + C); Assembly Language:  MOV EAX,A            MUL B            ADD EAX,C            CALL WriteInt Intel Machine Language: A1 00000000 F7 25 00000004 03 05 00000008 E8 00500000 ### 基本運算系統 ![image](https://hackmd.io/_uploads/rka_wOcQp.png) ### ARM 架構 * 32-bit RISC-processor core (32-bit instructions)32 位元 RISC 處理器核心(32 位元指令) * 37 pieces of 32-bit integer registers (16 available)37個32位元整數暫存器(16個可用) ### ARM instruction set指令集(六大類指令) * ==Load載入== and ==store儲存== instructions(==data transfer資料傳輸==) * ==Data processing資料處理== instructions(==arithmetic and logic算術和邏輯==) * ==Branch分支== instructions(control flow) * ==Status register狀態暫存器== ==transfer傳輸== instructions(flag operations) * ==Exception-generating異常產生== instructions(SWI & BKPT) * ==Coprocessor協同處理器== instructions ## CH2 Programmer’s Model 存資料的地方:**Memory/Memory map、Registers** <font color="#00f">Memory/Memory map:記憶體映射技術是將系統上裝置兩組記憶體,透過映射動作產生兩組資料完全相同的記憶體,等於有了個完全一模一樣的備份記憶體系統。當其中一組記憶體損壞時,便可利用記憶體熱抽換技術更換記憶體,系統將可維持不中斷,完全不影響企業正常作業,確保資料儲存的安全性。</font> What happens when you give the machine an ==invalid instruction無效指令==? **Operational flags: Status and Control flags操作標誌:狀態和控制標誌** ==Exceptions(例外): Processor modes處理器模式== ### Data types * Byte (8-bit) * Halfword (16-bit):讀/寫必須與兩位元組邊界==對齊aligned== * Word (32-bit):字元必須與四位元組邊界==對齊aligned== ### Endianness位元組順序 **Little-endian aligning小端對齊** <font color="#00f">A byte(halfword) at a word-aligned address is the least significant byte(halfword) within the word at that address字對齊位址處的位元組是該位址處字內的最低有效位元組</font> **Big-endian aligning大端對齊** <font color="#00f">A byte(halfword) at a word-aligned address is the most significant byte(halfword) within the word at that address字對齊位址處的位元組是該位址處字內的最高有效位元組</font> ### Processor modes處理器模式 * **USER(usr)用戶模式**: Normal program execution執行 state * 大多數應用程式將在 USER 模式下執行 * 正在執行的程式無法存取某些受保護的系統資源或變更模式 * **FIQ(fiq)快速中斷模式**: Data transfer state (fast irq, DMA-type transfer)用於高速數據傳輸或通道處理。 * **IRQ(irq)外部中斷模式**: Used for ==general interrupt services一般中斷服務== * **SUPERVISOR(svc)管理模式**: Protected mode for operating system support * **ABORT(abt)數據訪問中止模式**: Selected when data or instruction fetch is aborted當資料或指示取得被中止時選擇 * **SYSTEM(sys)系統模式**: Operating system ==‘privilege特權’==-mode for user * privilege mode特權模式 * have full access to system resources * Can change mode freely * Each of them has a ==service routine服務例程== (in operating systems) * Each of them has some additional registers to avoid corrupting User mode state * **UNDEFINIED(und)未定義指令中止模式**: Selected when undefined instruction is fetched ### ARM register暫存器 ARM 總共有 37 個暫存器 **general-purpose registers通用暫存器:31個** * The unbanked registers通用暫存器: R0 ~ R7 * The banked registers分組暫存器: R8 ~ R14 * r13 : 堆疊暫存器(SP/Stack Pointer) : 指向目前處理器模式的堆疊的堆疊頂端 * 14 : 連結暫存器 (LR/Link Register) : 存放(副)函數返回的位置,可在==exception occurs異常發生==時自動儲存返回地址 * Register 15程式計數器, the (PC/ Program Counter) : 儲存、指向下一道要執行的指令的位置 * There are many ==instruction-specific restrictions特定指令限制== or special cases about its use * The ==instruction指令== is ==UNPREDICTABLE不可預測== if R15 is used in a manner that breaks these ==restrictions限制== **Program status registers狀態暫存器:6個** * CPSR: ==Current Program Status Register目前程式狀態暫存器==:儲存 “flag bits”(條件旗標)、中斷位元、紀錄Arm模式… * SPSR: ==Saved Program Status Register儲存程式狀態暫存器==:當異常出現時,用來儲存 CPSR 值,以便異常處理結束後返璇工作狀態 ### Flags ![image](https://hackmd.io/_uploads/ry1Alq9Q6.png) * Condition code flags: N, Z, C, V * N : Negative If this result is regarded as a two's complement signed integer, then N = 1 if the result is negative and N = 0 if it is positive or zeroN=1 結果為負數N=0 結果為正數 or 零 * Z : Zero Is set to 1 if the result of the instruction is zero (which often indicates an equal result from a comparison), and to 0 otherwise. * C : Carry * ==C is set to 1== if the ==addition produced a carry加法產生進位== (that is, an unsigned overflow), and to 0 otherwise. * ==C is set to 0== if the ==subtraction produced a borrow減法產生借位== (that is, an unsigned underflow), and to 1 otherwise * For non-addition/subtractions that incorporate a shift operation, C is set to the last bit shifted out of the value by the shifter.對於包含移位操作的非加法/減法,C 被設定為移位器移出值的最後一位。 * For other non-addition/subtractions, ==C is normally left unchanged(C不變)== * V: oVerflow For an ==addition加法== or ==subtraction減法==, V is set to 1 if signed overflow occurred, regarding the operands and result as two's complement signed integers * Control bits: I, F, T The control bits change when an ==exception異常== arises and can be altered by software only when the processor is in a ==privileged mode== * Mode bits: M4, M3, M2, M1, M0 ### Address space * Directly直接 access address space—flat (physical) address space * Addressing lines尋址行 : n-bit * Addressing space尋址空間 = 2n bytes * Memory space allocation分配 * ==Dedicated (reserved)專用(保留)== memory space * Free (User) space * Memory-mapped I/O space #### Exception例外(異常) * Exceptions are generated by ==internal and external sources內部和外部來源== to cause the processor to handle an event, e.g., ==an externally generated interrupt外部生成的中斷== or an ==attempt to execute執行 an undefined instruction.== * The processor state just before handling the exception must be preserved保留 so that the original program can be resumed恢復 * More than one exception can arise at the same time #### Reset重置 * When the Reset input is asserted輸入 on the processor, the ARM processor immediately立即 stops execution of the current instruction * After Reset, the ARM processor ==begins execution at address 0x00000000 or 0xFFFF0000== in Supervisor mode with ==interrupts disabled停用中斷== ## CH3 Tutorial: First Programs ### Instructions指令 * **==Pseudo instruction偽指令==** (Directive instruction) * An element元素 in an assembly language that is similar to an instruction but ==provides control information== to the assembler ==as opposed不是== to ==generating a particular instruction== * Not part of the Intel instruction set * Used to ==declare code聲明程式碼==, ==data areas資料區==, ==select memory model選擇記憶體模型==, ==declare procedures聲明流程==, etc. * **Executable instructions可執行指令**(machine instructions) * Executed at runtime by the CPU #### An assembly instruction statement contains包含 four fields * Label標籤 (optional) * Act as place markers地點標記 * marks the address (offset) of code and data * Follow **identifier標識碼** rules * Data label * **must be unique: example: myArray** * Code label * target of jump and loop instructions * Mnemonic助記詞 (required) ![image](https://hackmd.io/_uploads/rkx57jc76.png) * Operand操作數 (depends on the instruction) * Constant or constant expression常量或常量表達式 * Constants and constant expressions are often called immediate values即時值 * Register * Memory (data label) * Comment註解 (optional) * Begin with semicolon (;) * Explain the program's purpose目的 * When it was written, and by whom * Revision information修訂資訊 * Tricky coding techniques棘手的編碼技術 * Application-specific explanations特定於應用程式的說明 ### Program 1: Shifting data 平移資料 ```AREA Prog1, CODE, READONLY ENTRY MOV R0, #0X11 ; Load initial value MOV R1, R0, LSL #1 ; Shift 1 bit left MOV R2, R1, LSL #1 ; Shift 1 bit left STOP B STOP ; Stop program END ``` instruction destination, source, source MOV : 移動 MOV R0, #0X11 : 將11值移動到位置R0 MOV R1, R0, LSL #1: 將整個r0向左平移1格後的值給給R1 ### Program 2: Factorial calculation階乘 ```AREA Prog2, CODE, READONLY ENTRY MOV R6, #10 ; Load 10 into R6 MOV R4, R6 ; Copy n into a temp register LOOP SUBS R4, R4, #1 ; Decrement next multiplier MULNE R7, R6, R4 ; Perform multiply MOV R6, R7 BNE LOOP ; Go again if not complete STOP B STOP ; Stop program END ``` LOOP : 迴圈 SUBS : 減法    => SUBS R4, R4, #1 =>將R4值減1後放入R4中 MULNE : 乘法 => 將R6與R4值相乘後放入R7 BNE LOOP : 若R4、R6、R7皆不為0 => 繼續迴圈 ### 基本指令 ![](https://hackmd.io/_uploads/ry8zyouM6.jpg) 巨集指令:用一整個小程式作為一個指令 嵌入式系統:Embedded Systems *ALIGN=>對其,在拿取資料的時候可以一次拿? ex: ALIGN 4,3=> 儲存空間以四個為一組,放在的三個位置(位置從0開始數) *SPACE:預留塊記憶空間 *LTORG:用來支持ON裡面的指令(不常用) ## CH4 Assembler Rules and Directives 組合器規則和指令 ### Structure of assembly language modules組合語言模組的結構 ``` AREA ARMex, CODE, READONLY ; Name this block of code ARMex 將此程式碼區塊命名為 ARMex ENTRY ; Mark first instruction to execute 標記要執行的第一條指令 ... ; Executable or pseudo instructions 可執行或偽指令 END ; Mark end of code ARMex 標記程式碼結束 ARMex ``` ### 指令格式 ``` label instruction或directive或pseudo-instruction ;comment ``` ==label標籤== ==instruction指令或directive指令或pseudo-instruction偽指令== ==;comment註解== * **指令**不能從第一列開始(若前面沒有符號,須以空格開頭) #### Label * To represent ++variables變數++, ++addresses位址++, and ++numeric constants數值常數++ * Must begin in the ++first column第一列++ * Character-set: {uppercase/lowercase letters, numeric characters, or the underscore character} 字元集:{大寫/小寫字母、數字字元或底線字元} * Do **not** use ==numeric characters數字字符== for the first character of symbol names, **except in local labels** * Symbol符號 names are **case-sensitive區分大小寫** * 符號中每個字元都很重要 * 須確保此名稱在使用範圍內為唯一的 * Symbols must **not use** ==built-in variable names內置變數名稱== or ==predefined symbol names預定義的符號名稱== * Symbols must not use the same name as ==instruction mnemonics指令助記符== or ==directives與指令相同的名稱== e.g., <font color="#f00"> START_AT, LOOP_FOR, …</font> :::info 在組合語言中要實現流程控制時,往往需要讓程式計數器前移或後移一段距離(例如前移5個位元),移動的距離會因程式碼變動而不同,例如在某處增加(或刪除)一行程式碼,程式中所有有越過更改程式碼的前移(及後移)指令都要重新計算需移動的距離。這樣的程式在閱讀時需經過計算才能知道任何跳躍指令的終點,程式的可讀性顯然不佳。 標記可以避免上述的問題。可以在程式任何需要的位置加上不同標記,跳躍指令直接指定其終點對應的標記,不需用人工計算程式計數器移動的距離。而且還可以使用有意義,可讀性高的標記,更加提昇程式的可讀性。 ::: 以下是一段使用標記的組合語言程式: ```AREA Prog1, CODE, READONLY mov $v0, 0 MyLabel: ; 此處為一個名稱為MyLabel的標記 add $v0, $s0 ; 迴圈本體中的程式 subi $t0, 1 ; 迴圈本體中的程式 bne $t0, $zero, MyLabel ; 條件跳躍至MyLabel標記處 ; 若指定條件不滿足,繼續執行後續的程式 ``` #### Instruction/directive/pseudo-instruction field 指令/指令/偽指令字段 Must be preceded by a white space前面必須有一個空格 指令集 ![image](https://hackmd.io/_uploads/HJenTUcdLp.png) #### Comment field 註記 * 註記難以理解部分 * The first semicolon分號 on a line indicates表示 the beginning of a comment—==unless in the string constant; e.g., “string ;”除非在字串常數中; 例如,“字串;”== #### 組語常用常量 * Numeric constants * Decimal十進制 : 123 * Hexadecimal十六進制 : 0x3F * n進制:n_XXX => n表示2~9,XXX表示實際值 ex:5_4214 => 五進制,4214為實際值 Predefined register預先定義的暫存器 names:要區分大小寫 #### 預先聲明的暫存器(r0~r15): |register暫存器 | 名稱 | | -------- | -------- | | r0~r3 |a1-a4(argument參數, result結果, or scratch registers暫存暫存器) | |r4~r11 | variable registers變數暫存器(v1~v8) | |r9 | static base靜態基地(sb and SB)| |r10 |stack limit堆疊限制(sl and SL)| |r11 |frame pointer影格指標(fp and FP )| |r12 |intra-procedure-call scratch register過程內呼叫暫存暫存器(ip and IP )| |r13 |stack pointer堆疊指標(sp and SP )| |r14 |link register連結暫存器(lr and LR )| |r15 |program counter程式計數器(pc and PC )| #### Frequently used directives指令 | Directive | Comment| | -------- | -------- | | AREA | Defines a block區塊 of data or code | | RN | Equates等於 a register with name| | EQU | Equates a label to a numeric constant| | ENTRY |Declares an entry point to your program| | DCB | Allocate one or more bytes of memory. It also specifies the initial runtime contents of memory 分配一個或多個位元組的記憶體。 它還指定記憶體的初始運行時內容| | DCW |Allocate one or more halfwords of memory including initial run time contents 分配一個或多個半字內存,包括初始運行時內容 | | DCD | Allocate one or more words of memory including initial run time contents分配一個或多個記憶體字,包括初始運行時內容| | ALIGN | Aligns data or code to a particular memory boundary 將數據或代碼與特定記憶體邊界對齊| | SPACE |Reserves a zeroed block of memory of a particular size 保留特定大小的歸零記憶體區塊| | LTORG | Assigns the string point of a literal pool分配文字池的字串點| | END | Designates the end of a source file指定原始檔的結尾| * **AREA** * The AREA directive instructs the assembler to assemble a new code or data sectionAREA 偽指令指示彙編器彙編新的程式碼或資料部分 * Sections節 are independent獨立的, named命名的, ==indivisible chunks不可分割的== of code or data that are manipulated by the linker連結器 * Syntax語法:![image](https://hackmd.io/_uploads/rySPFCVup.png) * Namesstarting with a digit數位 must be enclosed in bars小節; e.g., ==|123_Digital|== * **attr** are one or more comma-delimited以逗號分隔 section部分 attributes屬性 * **CODE** : Contains machine instructions. ==READONLY== is the default預設值 * **DATA** : Contains包含 data, not instructions指令. READWRITE is the default * **READONLY**:表示此部分不應寫入這是代碼區域的預設值 * **READWRITE**:表示此部分可以讀取和寫入這是數據區域的預設值 * 使用 AREA 指令將==源檔source file==細分為多個部分 * 大型程式通常可以方便地分為幾個程式碼段 * 範例: ```AREA Prog1, CODE, READONLY AREA Example, CODE, READONLY ; an example code section示例代碼節 ``` * RN * RN 指令定義指定暫存器的寄存器名稱 * 語法:![image](https://hackmd.io/_uploads/SyRcC0Vdp.png) * where * **name** : 分配給暫存器的名字,不可與處理器中任何預設值得名稱相同 * **expr** :暫存器編號 * 範例: ```AREA Prog1, CODE, READONLY coeff1 RN 8 ; r8 = coeff1 coeff2 RN 9 ; r9 = coeff2 dest RN 0 ; r0 = dest ``` * **EQU** * 為數值常量、暫存器相對值或程序相對值提供符號名稱 * EQU 的同義詞 : ==*== * 類似於在 C 中使用 #define 定義常量 * 實際上不會在特定的記憶體位置放置任何內容 * 語法:![image](https://hackmd.io/_uploads/SyaWfyrOT.png) * **name**:分配給值的符號名稱 * **expr**:暫存器相對位址、程序相對地址、絕對位址或32位整數常量 * **type**:可以是以下任一(代碼16、代碼32、數據) ```AREA Prog1, CODE, READONLY abc EQU 2 ; 將值 2 賦給符號 abc xyz EQU label+8 ; 將地址(標籤+8)分配給符號xyz fiq EQU 0x1C, CODE32 ;將絕對位址 0x1C 分配給符號 fiq,並將其標記為代碼marks it as code ``` * **ENTRY** * 聲明程式的入口點 * 語法:![image](https://hackmd.io/_uploads/HJ7AXkS_T.png) * 如果不存在 ENTRY,則在連結時產生警告 * 不得在單一來源檔案中使用多個 ENTRY 指令 * 並非每個原始檔都必須有 ENTRY 指令 * 如果單一來源檔案中存在多個 ENTRY => error ```AREA Prog1, CODE, READONLY AREA ARMex, CODE, READONLY ENTRY ; 應用程式的入口點 ``` * **DCB** : 分配一個或多個字節的記憶體,並定義記憶體的初始運行時內容,同義詞為===== * 語法:![image](https://hackmd.io/_uploads/B1JIUJrOa.png) * **expr**:計算結果為 –128 到 255 範圍內的整數或引號的字串的數值表達式,字串的字元被載入到儲存的連續位元組中。如果 DCB 後面接著指令,請使用 ALIGN 指令來確保指令對齊 * **DCW and DCWU** * DCW 指令分配一個或多個半字記憶體,在 2 位元組邊界上對齊,並且定義記憶體的初始運行時內容 * DCWU 是相同的,只是記憶體對齊是任意的 * 語法:![image](https://hackmd.io/_uploads/r1XqYkrOp.png) * **expr**:是一個數值表達式,其計算結果為 –32768 到 65535 範圍內的整數 * 如有必要,DCW 會在第一個定義的半字之前插入inserts 一個字節填充padding,以實現 2 位元組對齊 * 如果不需要對齊alignment,請使用DCWU * **DCD and DCDU** * DCD指令分配allocate一個或多個記憶體字,在4位元組邊界上對齊aligned,並定義記憶體的==initial runtime contents of the memory初始運行時內容== * DCDU 是一樣的,只是記憶體對齊是arbitrary任意的 * 語法:![image](https://hackmd.io/_uploads/BJ3g2kSO6.png) * **expr**: * A numeric expression數值表達式 * A program-relative expression與程式相關的表達式 * DCD 在第一個定義的字之前插入最多 3 個位元組的填充,以實現 4 位元組對齊 * Use DCDU, do not require alignment 範例: ```AREA Prog1, CODE, READONLY data1 DCD 1,5,20 ; 定義 3 個單詞,其中包含十進制值 1、5 和 20 data2 DCD mem06 + 4 ; 定義 1 個包含 4 + 的單字標籤mem06的地址 coeff DCW 0xFE37, 0x8ECC ; 定義2個半字 AREA MyData, DATA, READWRITE DCB 255 ; Now misaligned ...現在錯位了... data3 DCDU 1,5,20 ; 定義 3 個單詞,其中包含1、5 和 20,未字對齊 ``` * **ALIGN** * 通過用零填充將當前位置與指定邊界對齊 * 語法: ![image](https://hackmd.io/_uploads/HyEOXgSda.png) * **expr**:是一個數值表示式,計算值為 2的任意冪次 從 2⁰到2³¹ * **offset** :任何數值表達式 * 目前位置與表單的下一個位址對齊:offset + n * expr * 如果未指定 expr,則 ALIGN 將當前位置設置為下一個字(四位元節)邊界 * 範例: ```AREA Prog1, CODE, READONLY AREA OffsetExample, CODE DCB 1 ALIGN 4, 3 DCB 1 ;此範例將兩個位元組放置在同一字的第一個和第四個位元組中 AREA Example, CODE, READONLY Start LDR r6, =label1 ; code MOV pc, lr label1 DCB 1 ALIGN subroutine1 ; pc 現在未對齊確保子程式 1 尋址以下指令 MOV r5, #0x5 ``` * **SPACE** * Reserves保留一個歸零的記憶體塊,同義詞為% * 語法:![image](https://hackmd.io/_uploads/B1YnLeBua.png) * **expr** :計算結果為要保留的零位元組數 * 使用 ALIGN 指令對齊 SPACE 指令後面的任何代碼 * 範例: ```AREA Prog1, CODE, READONLY AREA MyData, DATA, READWRITE data1 SPACE 255 ; defines 255 bytes of zeroed store定義 255 位元組的歸零存儲 ``` ## CH5 Data Transfer: Loads, Stores, and Addressing數據傳輸:載入、存儲和尋址 ### 載入與儲存指令 | 指令| 意義 | | -------- | -------- | | LDR/LDM| : LoaD Register/LoaD Multiple多個 registers | |STR/STM |store儲存 Register/STore Multiple registers| | MOV/MVM | MOVe/MoVe Not| |PLD |cache preLoad緩存預載入| | SWP |在暫存器和記憶體之間交換數據| ### 資料處理指令 ```AREA Prog1, CODE, READONLY MOV R0, #0 ; 將數值0存入R0中 ADD R3, R3, #1 ; R3=R3+1 CMP R7, #1000 ; R7-1000 BIC R9, R8, #0xFF00 ; Clear bits 8-15 of R8 and store in R9, ;ex:r8=0x25496178 => r9=0x25490078 ``` CMP 功能相当于减法指令,只是不保存结果,仅仅根据计算结果对标志暫存器进行设置 ```AREA Prog1, CODE, READONLY MOV R2, R0 ; 將R0中的值給R2 ADD R4, R3, R2 ; R4=R3+R2 CMP R7, R8 ; R7-R8 ``` ```AREA Prog1, CODE, READONLY MOV R2, R0, LSL #2 ; (R2=R0x4) ADD R9, R5, R5, LSL #3 ; R9=R5+ (R5 x 2^3) RSB R9, R5, R5, LSL #3 ; R9=(R5 x 2^3) - R5 SUB R10, R9, R8, LSR #4 ; R10=R9 - (R8/2^4) MOV R12, R4, ROR R3 ; R12 = R4的值向右移R3個單位(以二進制值右移) ``` "**ror eax, 1**"将把暫存器eax中的二进制数向右移动1位,同时将移出的最右一位放到eax的最高位上。 #### Example: immediate and register offset ```AREA Prog1, CODE, READONLY ;Word LDR R1, [R0] ; R1=R0所指的記憶體位置中的值(四個byte) LDR R8, [R3, #4] ; R8 =(R3+4)所指的記憶體位置中的值 LDR R12, [R13, #-4] ; R12 =(R3-4)所指的記憶體位置中的值 STR R2, [R1, #0x100] ; 將R2中的值存到記憶體中(R1 + 0x100)的位置 STR R2, [R1], #4 ;將R2中的值存到記憶體中(R1)的位置,再令暫存器中R1=R1+4 ``` ```AREA Prog1, CODE, READONLY ; Byte LDRB R5, [R9] ; 將R9所指的記憶體位置中的一個byte放入R5暫存器中(一個byte=2個位元) ; (zero top 3 bytes) LDRB R3, [R8, #3] ; 將(R8+3)所指的記憶體位置中的一個byte放入R3暫存器中 ; (zero top 3 bytes) STRB R4, [R10, #0x200] ; 將R4暫存器中的一個byte存入(R10 + 0x200)所指的記憶體位置中 ``` ```AREA Prog1, CODE, READONLY LDRH R1, [R0] ; 將[R0]所指的記憶體位置中的兩個byte放入暫存器R1中 ; (zero top 2 bytes) LDRH R8, [R3, #2] ; 將[R3+2]所指的記憶體位置中的兩個byte放入暫存器R8中 LDRH R12, [R13, #-6] ; 將[R3-6]所指的記憶體位置中的兩個byte放入暫存器R12中 STRH R2, [R1, #0x80] ; 將R2暫存器中的兩個byte存入(R1 + #0x80)所指的記憶體位置中 ``` ```AREA Prog1, CODE, READONLY LDRSH R5, [R9] ; 將[R9]所指的記憶體位置中的兩個byte放入暫存器R5中 LDRSB R3, [R8, #3] ; 將[R8+3]所指的記憶體位置中的兩個byte放入暫存器R3中 LDRSB R4, [R10, #0xC1] ; 將[R10 + 0xC1]所指的記憶體位置中的兩個byte放入暫存器R4中 ``` ```AREA Prog1, CODE, READONLY LDRH R11, [R1, R2] ; 將[R1+R2]所指的記憶體位置中的兩個byte放入暫存器R11中 STRH R10, [R7, -R4] ; R10暫存器中的兩個byte存入(R7 - R4)所指的記憶體位置中 LDR R11, [R1, R2] ; 將[R1+R2]所指的記憶體位置中的值放入暫存器R11中 STRB R10, [R7, -R4] ; R10暫存器中的一個byte存入(R7 - R4)所指的記憶體位置中 ``` **中括號[]:記憶體位置** Example: Scaled register offset ```AREA Prog1, CODE, READONLY LDR R11, [R3, R5, LSL #2] ;將 [EA=R3 + (R5 x 2^2)]所指的記憶體位置中的值存入暫存器R11中 STR R7, [R1, R3, LSR #3] ; 將暫存器R7中的值存入[R1 + (R3 / 2^3)]所指的記憶體位置中 ``` ```AREA Prog1, CODE, READONLY LDR R1, [R0, #4]! ;R1 =記憶體位置[EA=R0 + 4] ; then R0 = 記憶體位置 STRB R7, [R6, #-1]! ; 將暫存器R7中的一個byte存入記憶體位置[EA=R6 – 1], ; then R6 = EA LDRSH R1, [R0, #2]! ; R1=記憶體位置[EA=R0 + 2]中的兩個byte ; then R0 = EA LDRSB R7, [R6, #-1]! ; R7=記憶體位置[EA=R6 – 1]中的一個byte ; then R6 = EA LDR R11, [R3, R1] ! ; R11=記憶體位置[EA=R3 +R1]中的值 ; then R3 = EA STR R7, [R1, -R3]! ; 將暫存器R7中的值存入記憶體位置[EA=R1-R3], ; then R1 = EA ``` ```AREA Prog1, CODE, READONLY LDRH R3, [R9], #2 ; Load halfword to R3 from mem[EA=R9], ; then R9 = R9 + 2 STRH R2, [R5], #8 ; Store halfword from R2 to mem[EA=R5], ; then R5 = R5 + 8 LDR R0, [R1], R2 ; Load R0 from mem[EA=R1] ; then R1 = R1 + R2 LDR R0, [R1], R2, LSL #2 ; Load R0 from mem[EA=R1] ; then R1 = R1 + R2 x 4 ``` <font color="#f00">**!**</font> : * 更新暫存器中的值 * 對於暫存器清單中的每個暫存器,它遞減或遞增一個字 <font color="#f00">register-list</font> : 用大括弧括起來的符號暫存器名稱和暫存器範圍的逗號分隔清單。       example : {r0,r1,r4-r6,pc} Example **?** ```AREA Prog1, CODE, READONLY STMFD r13!, {r0-r5} ; Push onto a Full Descending Stack LDMFD r13!, {r0-r5} ; Pop from a Full Descending Stack subroutine STMFD sp!, {r5-r7,lr} ; Push work registers and lr ; code BL somewhere_else ; code LDMFD sp!, {r5-r7,pc} ; Pop work registers and pc ``` ```AREA Prog1, CODE, READONLY STMFD R13!, {R1} ;將暫存器R13中的值減4,再將R1中的值放入R13所指的記憶體位置中 ```