# ARM Befehle

## ARM 7

- Architektur: ARM v4T, Prozessor ARM7 TDMI
- 1994 rausgekommen
- 12-70 MHz, 0,889 DMIPS/MHz
- [RISC](Klassifikation.md#risc-prinzipien), Load-Store-Architektur
- 3-stufige [Pipeline](MU7Rechner.md#pipeline)
- Instruction Set
  - ARM 32 bit oder Thumb
  - [3-Adress-Befehle](Klassifikation.md#3-adress-befehle)
- Little Endian als Standard

### ARM-Datenpfad

![image_302.png](image_302.png)

### ARM7-ALU

![image_303.png](image_303.png)

### ARM7-Pipeline für ALU-Befehle

![image_304.png](image_304.png)

- Latenz
  - 3 Zyklen
- Durchsatz
  - 1 Befehl je Zyklus

#### Multi-cycle Execution

- Execute benötigt einen Takt für simple Instruktionen
- Bei Speicherzugriff mind. 2 Takte
  - Adress Berechnung
  - Speicherzugriff
- ![image_305.png](image_305.png)

## Load/Store Befehle Hazard in Von-Neumann

![image_306.png](image_306.png)

![image_307.png](image_307.png)

## ARM Registerstruktur

![image_309.png](image_309.png)

## Statusflags

- **N** (Negative)
  - Das Ergebnis der ALU ist negativ (Bit 31=1)
- **Z** (Zero)
  - Das Ergebnis der ALU ist Null (Bit 0..31 = 0)
- **C** (Carry)
  - Bei arithmetischer Operation wird C auf Carry-Out der ALU gesetzt
  - Sonst auf Carry-Out des Shifters bzw. ohne Shift Operation bleibt C erhalten
- **V** (Overflow)
  - Wenn Zahlensystem geändert wird
  - Wenn mit unsigned gerechnet wird ist V ohne Interesse

## Current Program Status Register (CPSR)

- ![image_310.png](image_310.png)
- **T-Bit**
  - T = 0
    - Prozessor in Arm State
  - T = 1
    - Prozessor in Thumb State
- **Interrupt Disable Bit**
  - I = 1, disables IRQ
  - F = 1, disables FIQ
- **Mode Bits**
  - Spezifizieren Prozessor Mode

## Übersetzungstabelle Assembler - Binärcode

![image_311.png](image_311.png)

## Thumb Befehlsatz

- zusätzlicher Befehlssatz
  - 16 Bit
  - Intern werden sie auf 32 Bit erweitert
    - Programme verbrauchen nur halben Speicher
      - weniger Register stehen zur Verfügung
    - Während Programmausführung kann zwischen ARM-32 und Thumb gewechselt werden
- Thumb-2 ist ein gemischter 16/32 Bit Befehlssatz
- Prozessor ARM7TDMI unterstützt sowohl ARM als auch Thumb

## ARM Befehlssatz

- Drei Befehlstypen
  - zur Datenverarbeitung (bspw. Addition)
  - Ablaufsteuerung (bspw. Verzweigungen)
  - Befehle zur Adressierung
- Groß-Kleinschreibung wird ignoriert

### ARM-Befehle: MOV

- MOV ist ein Datentransferbefehl
  - Kopiert Daten in ein Register
- Beispiele
  - mov r0, r1 @Inhalt von R1 wird nach R0 kopiert
  - mov r1, #0 @Zahl 0 wird nach R1 kopiert
  - mov pc, lr @PC wird auf LR gesetzt
- Variante:
  - mvn r1, r2
    - Wendet zusätzlich zu mov ein EOR auf Inhalt von r2 an

### ARM-Befehle: ADD

- Die arithmetischen Befehle der ARM Prozessoren sind 3-Register-Befehle
  - Alle Operanden sind 32Bit
  - Das Ergebnis ist 32 Bit
  - 3 Operanden: 2 als Input, 1 als Ergebnis
- Beispiel
  - ADD r0, r0, r3 @R0 = R0 + R3

### ARM-Befehle: SUB

- ARM-Prozessoren implementieren keine Subtraktion
  - Addition mit 2er Komplement
- Beispiel
  - SUB r0, r0, r3 @R0 = R0 - R3 = R0 + (-R3)

### ARM-Befehle: CMP

- Befehl vergleicht zwei Werte auf Gleichheit und setzt Statusflags entsprechend
  - CMP r0, #5 @r0 == r5?
- Dazu wird folgende Berechnung (r0=3) ausgeführt
  - CMP r0, #5 @r0-5 = 3-5 ausgeführt
    - MOV r1, #5
    - SUBS r1, r0, r1
- Folgende Statusflags werden gesetzt
  - ![image_312.png](image_312.png)

### ARM-Befehle: -S

- Setzen des Statusregisters bei arithmetischen und logischen Befehlen
- Bedingungsbits des Statusregisters werden nur bei Test-/Compare-Befehlen automatisch gesetzt
- Alle anderen Befehle müssen explizit setzen
- Beispiel
  - add r0, r0, r3 @lässt Statusregister unverändert
  - subs r0, r0, #1 @schreibt alle Flags NZCV

### ARM-Befehle: - {cond}

- Jeder Befehl kann bedingt ausgeführt werden
  - Bedingung (bezogen auf vorher gesetzte Werte des Statusregisters) als Ergänzung an den Befehl angehängt
- Beispiel
  - CMP r0, #5
  - ADDNE r1, r1, r0
  - SUBNE r1, r1, r2
  - if (r0 != 5) {r1 = r1+r0-r2}
- NE = not equal
  - Bezogen auf die vorherigen Werte des Statusregisters

#### Bedingte Ausführung von Befehlen

![image_313.png](image_313.png)

##### Signed/unsigned

![image_314.png](image_314.png)

##### carry set / higher same

- Beispiel:
  - CMP r0, r1 @berechnet R0-R1, also R0 + (-R1) und setzt NZCV
  - JCS sprungziel @springt zur Marke "sprungziel", wenn CS erfüllt ist
- Bedeutung: Wenn **unsigned >=** dann C gesetzt
  - R0 = 3,R1 = 2 (nur 4-Bit Darstellung)
  - R0 = 0011 2k = 1110
  - Berechnet: 0011 + 1110 = 3 + (-2) = 0001
    - C = 1
  - R0 = 2, R1 = 3 (nur 4-Bit Darstellung)
  - R0 = 0010 R1 = 0011
  - Berechnet: 0010 + 1101 = 2 + (-3) = 1111
    - C = 0

##### Bedingte Ausführung LT (Less than)

- Beispiel
  - CMP R0, R1 @berechnet R0-R1 und setzt NZCV
  - JLT sprungziel @springt zur Marke "sprungziel", wenn CS erfüllt ist
- Bedeutung: wenn **signed <** dann N ungleich V
- Beispiel 1
  - R0 = 3, R1 = 4 (nur 8 Bit)
  - R0 = 00000011 R1 = 00000100
  - Berechnet: 00000011 + 11111100 = 3 + (-4) = 11111111
    - N = 1, V = 0
- Beispiel 2
  - R0 = -127, R1 = 2
  - R 0 = 10000001 R1 = 00000010
  - Berechnet: 10000001 + 11111110 = -127 + (-2) = 127 (?)
    - N = 0, V = 1

### ARM-Befehle: Der Barrel Shifter

![image_315.png](image_315.png)

#### LSL: Logical Shift Left = Arithmetic Shift Left (ASL)

- ![image_316.png](image_316.png)
- Multiplikation mit einer Zweier-Potenz
- ![image_317.png](image_317.png)
  - LSL R0, R1, #5 -> R0 = R1*2^5

#### LSR: Logical Shift Right

- ![image_318.png](image_318.png)
- Division durch eine Zweier-Potenz
- ![image_319.png](image_319.png)
  - LSR R0, R1, #5 -> R0 = R1/2^5

#### ASR: Arithmetic Shift Right

- ![image_320.png](image_320.png)
- Division durch eine Zweier-Potenz unter Erhaltung des Vorzeichens
- ![image_321.png](image_321.png)
  - ASR #5, positiver Operand

#### ROR: Rotate Right

- ![image_322.png](image_322.png)
- ![image_323.png](image_323.png)

#### RRX: Rotate Right Extended

![image_324.png](image_324.png)

#### Multiplikation mit einer Konstanten

- mit 2^x oder als 2^x +-1 darstellen lassen
  - können in einem Zyklus durchgeführt werden
  - Beispiel: Mul mit 5
    - ADD r0, r1, r1, LSL #2
- Durch Zusammensetzen mehrerer Instruktionen können auch komplexere Multiplikationen durchgeführt werden
  - Beispiel: Mul 10
    - ADD r0, r1, r1, LSL #2
    - LSL r0, r0, #1 @mov r0, r0, LSL#1
  - Beispiel Mul mit 119 = 17·7 = (16+1)·(8-1)
    - ADD r2, r3, r3, LSL #4 @r2 = r3·17
    - RSB r2, r3, r2, LSL #3 @r2 = r2·7

## UAL (Unified Assembler Language)

- gemeinsamer Syntax für ARM32 und Thumb
  - gleicher Code für beide Modi
- Falls Befehl nicht umgesetzt werden kann
  - Assembler gibt Fehlermeldung aus
- Beispiel 1
  - vorher
    - Thumb: AND R0, R1
    - ARM: AND, R0, R0, R1
  - Jetzt: AND **R0, R0, R1**
- Beispiel 2
  - vorher
    - Thumb: LSL R0, R1, #2
    - ARM: MOV R0, R1, LSL #2
  - Jetzt: **LSL R0, R1, #2**

## Arithmetische und logische Befehle

![image_325.png](image_325.png)

### Binärcodierung arithmetischer und logischer Befehle

![image_326.png](image_326.png)

![image_327.png](image_327.png)

### Assembler Format
- Arithmetische und logische Befehle haben eins der beiden logischen Formate
  - \<op\>{\<cond\>}{S} -> Rd, Rn, #\<32-Bit-Immidiate\>
  - \<op>{\<cond\>}{S} -> Rd, Rn, Rm, {\<shift>}

- Rd: Destination
- Rn: Operand 1
- Rm: Operand 2

- Beispiel:
  - ADD r0, r1, r2
  - ADD r0, r2, #4
  - MOV r0, r1
  - ADDGTS r0, r1, r2, LSR r3

#### Operand 2 als Konstante (Immidiate)
- Befehlsformat für Datenverarbeitungsbefehle reserviert 12 Bits für Operand 2
  - ergäbe einen Wertebereich von max 2^12 = 4096
  - oder aufgeteilt in Wertebereiche mit 8 Bits (0-255)
- Diese 8 Bits können (links) rotiert werden
  - gerade Anzahl von Positionen (0, 2, 4, ..., 30)
- Ergibt weitaus größere Abdeckung des Zahlenbereichs
  - 8 zusammenhängende Bits innerhalb des 32-Bit-Wertebereichs
  - ![image_328.png](image_328.png)
- Einige Konstanten müssen dennoch vom Speicher geladen werden
  - oder in einem Register konstruieren
- ![image_329.png](image_329.png)

#### Operand 2 als Konstante
- Wertebereich
  - | 0-255                       | [0-0xff]                                   |
    |-----------------------------|--------------------------------------------|
    | 256, 260, 264, ..., 1020    | [0x100-0x3fc, step 4, 0x40-0xff ror 30]    |
    | 1024, 1040, 1056, ..., 4080 | [0x400-0xff0, step 16, 0x40-0xff ror 28]   |
    | 4096,4160, 4224,..,16320    | [0x1000-0x3fc0, step 64, 0x40-0xff ror 26] |
- Beispiel MOV-Befehl
  - MOV r0, #0xFF000000 @MOV r0, #0xFF, 8
- Beispiel MVN: erzeuge das bitweise 1er-Komplement
  - MOV r0, #0xFFFFFFFF @umgesetzt zu MVN r0,#0
- Falls benötigte Konstante nicht erzeugt werden kann
  - Assembler erzeugt Fehlermeldung

## Multiplikation
![image_330.png](image_330.png)

## Befehle zur Ablaufsteuerung
### Sprungbefehle (Branch)
- dienen dazu den Kontrollfluss von Programmen zu kontrollieren
- in Kombination mit Vergleichsbefehlen 
  - können alle wichtigen Anweisungen (if, else, while, for, switch) darstellen
- Ziel ist immer eine Marke (Label)
  - Assembler erzeugt Sprungadresse
- Beispiel
- ```
  CMP R0, #0
  BNE Marke 1
  ...
  ...
  Marke 1: MOV R5, #5
  ```
- ![image_331.png](image_331.png)

### Sprungbefehle
![image_332.png](image_332.png)

#### Unterprogramme (Branch-with-Link)
- Der Befehl BL führt einen Sprung aus
  - speichert die Rücksprungadresse im Link-Register r14(LR)
- Weitere Subroutinen müssen r14(LR) im Speicher sichern
  - bspw. auf Stack und bei Rückkehr in r15(PC) wieder herstellen
- Arbeitsregister können ebenfalls gesichert werden
  - wenn Unterprogramm diese benötigt
  - Übergabe von Parametern nach APCS-Standard
- Beispiel
  - ![image_333.png](image_333.png)

#### Sprungbefehle mit Mode-Wechsel (32Bit Thumb)
- **BX Rn Branch and Exchange**
  - Als Argument erhält der Befehl eine Registeradresse
    - Inhalt wird in PC kopiert
      - Falls ungerade → Wechsel in Thumbmode
      - Falls gerade → Wechsel in ARM-Mode
  - Befehl **BX LR** ist Standardbefehl um Unterprogramme zu verlassen
    - Rücksprungadresse steht noch im Linkregister
- **BXL Label - Branch and Link with Exchange**
  - Standardbefehl zum Aufruf von Unterprogrammen
  - wird in Programmen mit gemischtem 32-Bit/Thumb Code genutzt
- **BLX Rn**
  - Führt Modewechsel durch 
  - Speichert nächste Adresse im Linkregister

#### Unterprogrammaufruf mit Modewechsel
![image_334.png](image_334.png)


### Befehle zur Ablaufsteuerung - Beispiele
- ![image_335.png](image_335.png)
- Befehle MOV PC, Rd, ist nach Einführung des Thumb Befehlssatzes nicht mehr empfohlen
  - Lässt direkten Zugriff auf PC nicht zu
  - Stattdessen BX, BLX
- Alle Sprungbefehle können bedingt ausgeführt werden
- Offset der Sprungbefehle bis zu 32 MByte
  - FÜr größere Sprünge muss Zieladresse erst in ein Register geladen werden

### Assembler-Format der Sprungbefehle
![image_336.png](image_336.png)

## APCS (ARM Procedure Calling Standard)
- Standard definiert wie Funktionen geschrieben werden sollen
  - können unabhängig geschrieben, compiliert, assembliert uns später gelinkt werden
- Umfasst auch andere Programmiersprachen wie C
- Definiert sind
  - Anforderungen an aufrufende/aufgerufene Funktionen
  - Einschränkungen bei der Nutzung von Registern durch Funktionen
  - Daten- und Stacklayout und Konventionen
  - C/C++ Language Bindings, shared libs, reentrant code, etc.

### Parameterübergabe an Funktionen
- Funktionsaufruf:
  - Result = fct(ARG1, ARG2, ARG3, ARG4)
    - Parameter 1-4 in Register r0-r3 übergeben
    - Rückgabewert von Funktionen steht im Register r0 oder r0/r1
- Verwendung von Registern in der Funktion
  - r0-r3 und IP = Scratch Register
    - dürfen im Unterprogramm zerstört werden
  - Informationen in r4-r10, fp, sp dürfen nicht zerstört werden
  - Inhalt von lr wird zur Rückkehr ins aufrufende Programm benötigt
- ![image_337.png](image_337.png)

## [ARM Adressierung](arm_adressierung.md)