---
# System prepended metadata

title: 組合語言

---

# 組合語言
## 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所指的記憶體位置中
```

		







