405 lines
12 KiB
Markdown
405 lines
12 KiB
Markdown
# 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
|
|
|
|

|
|
|
|
### ARM7-ALU
|
|
|
|

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

|
|
|
|
- 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
|
|
- 
|
|
|
|
## Load/Store Befehle Hazard in Von-Neumann
|
|
|
|

|
|
|
|

|
|
|
|
## ARM Registerstruktur
|
|
|
|

|
|
|
|
## 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)
|
|
|
|
- 
|
|
- **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
|
|
|
|

|
|
|
|
## 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
|
|
- 
|
|
|
|
### 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
|
|
|
|

|
|
|
|
##### Signed/unsigned
|
|
|
|

|
|
|
|
##### 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
|
|
|
|

|
|
|
|
#### LSL: Logical Shift Left = Arithmetic Shift Left (ASL)
|
|
|
|
- 
|
|
- Multiplikation mit einer Zweier-Potenz
|
|
- 
|
|
- LSL R0, R1, #5 -> R0 = R1*2^5
|
|
|
|
#### LSR: Logical Shift Right
|
|
|
|
- 
|
|
- Division durch eine Zweier-Potenz
|
|
- 
|
|
- LSR R0, R1, #5 -> R0 = R1/2^5
|
|
|
|
#### ASR: Arithmetic Shift Right
|
|
|
|
- 
|
|
- Division durch eine Zweier-Potenz unter Erhaltung des Vorzeichens
|
|
- 
|
|
- ASR #5, positiver Operand
|
|
|
|
#### ROR: Rotate Right
|
|
|
|
- 
|
|
- 
|
|
|
|
#### RRX: Rotate Right Extended
|
|
|
|

|
|
|
|
#### 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
|
|
|
|

|
|
|
|
### Binärcodierung arithmetischer und logischer Befehle
|
|
|
|

|
|
|
|

|
|
|
|
### 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
|
|
- 
|
|
- Einige Konstanten müssen dennoch vom Speicher geladen werden
|
|
- oder in einem Register konstruieren
|
|
- 
|
|
|
|
#### 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
|
|

|
|
|
|
## 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
|
|
```
|
|
- 
|
|
|
|
### Sprungbefehle
|
|

|
|
|
|
#### 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
|
|
- 
|
|
|
|
#### 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
|
|

|
|
|
|
|
|
### Befehle zur Ablaufsteuerung - Beispiele
|
|
- 
|
|
- 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
|
|

|
|
|
|
## 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
|
|
- 
|
|
|
|
## [ARM Adressierung](arm_adressierung.md)
|